Parallel DWG Reads

Parallel DWG Reads

Anonymous
Not applicable
508 Views
1 Reply
Message 1 of 2

Parallel DWG Reads

Anonymous
Not applicable

Hi.

 

My application (a .DLL which I netload in) accesses several DWGs selected in a windows form app and collects some block attribute info about them. How can I do this in parallel?

 

I don't need to save the DWG at all during processing.

 

DWG.cs:

 

public class DWG
{

	public string DWGLocation;
	public string DWGName;
	public string DWGRev;
	public List<string> DWGLayouts;
	public string PDFName;
	public bool PDFExists;
	public bool IsDWGLocked;
	public bool IsPlotPDFLocked;
	public bool IsHistoricalPDFLocked;
	public bool IsReviewPDFLocked;

	// Class constructor based on passed parameter
	public DWG(string dwgToProcess)
	{
		DWGLocation = dwgToProcess;
		DWGName = Path.GetFileName(DWGLocation);
		PDFExists = File.Exists(FileOps.Path(DWGLocation) + GlobalVals.plotDir + PDFName);
		IsDWGLocked = FileOps.IsFileLocked(DWGLocation);
		IsPlotPDFLocked = FileOps.IsFileLocked(FileOps.Path(dwgToProcess) + GlobalVals.plotDir + PDFName);
		IsHistoricalPDFLocked = FileOps.IsFileLocked(FileOps.Path(dwgToProcess) + GlobalVals.historicalDir + PDFName);
		IsReviewPDFLocked = FileOps.IsFileLocked(FileOps.Path(dwgToProcess) + GlobalVals.reviewDir + PDFName);

		// Get the rev num and layout names from the DWG
		try
		{
			DWGRev = "?";
			List<string> layouts = new List<string>();

			using (Database db = new Database(false, true))
			{
				db.ReadDwgFile(dwgToProcess, FileShare.Read, false, null);
				db.CloseInput(true);

				using (Transaction tr = db.TransactionManager.StartTransaction())
				{

					// Layouts
					DBDictionary layoutDict = (DBDictionary)db.LayoutDictionaryId.GetObject(OpenMode.ForRead);
					foreach (DBDictionaryEntry entry in layoutDict)
					{
						if (entry.Key != "Model")
						{
							ObjectId layoutId = entry.Value;
							Layout layout = tr.GetObject(layoutId, OpenMode.ForRead) as Layout;
							layouts.Add(layout.LayoutName);
						}
					}
					DWGLayouts = layouts;

					// Attribute
					var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
					if (bt.Has(GlobalVals.titleblock))
					{
						// Open the block definition
						var btr = (BlockTableRecord)tr.GetObject(bt[GlobalVals.titleblock], OpenMode.ForRead);

						// Get the inserted block references ObjectIds
						var ids = btr.GetBlockReferenceIds(true, true);

						if (ids.Count > 0)
						{
							// Open the first block reference
							var br = (BlockReference)tr.GetObject(ids[0], OpenMode.ForRead);

							// Iterate through the attribute collection
							foreach (ObjectId id in br.AttributeCollection)
							{
								// Open the attribute reference
								var attRef = (AttributeReference)tr.GetObject(id, OpenMode.ForRead);

								// If the attribute tag is what we are searching for
								if (attRef.Tag.Equals(GlobalVals.revtag, StringComparison.CurrentCultureIgnoreCase))
								{
									DWGRev = attRef.TextString == "" || attRef.TextString == " " ? "R0" : attRef.TextString;
									break;
								}
							}
						}
					}
					tr.Commit();
				}
			}
			// Remove any spaces in the front or end of the REV val with trim in case of bad input
			DWGRev.Trim();
			PDFName = PDFOps.GetPDFName(DWGLocation, DWGRev);
		}
		catch (System.Exception ex)
		{
			ErrorHandler.ErrorReport(ex, "GetRevNum", "notify");
		}
	}
}

 

 

I create multiple instances of DWG like so:

 

 

foreach (string dwg in dialog.FileNames)
{
	// Check if the DWG already exists in list view to prevent duplicates in list view and list
	if (this.DwgList.FindItemWithText(dwg) == null)
	{
		// Create an instance of a DWG
		var dwgEntry = new DWG(dwg);

		// Make sure DWG is not locked
		if (!dwgEntry.IsDWGLocked)
		{
			// Make sure no PDFs are locked
			if (!dwgEntry.IsPlotPDFLocked && !dwgEntry.IsHistoricalPDFLocked && !dwgEntry.IsReviewPDFLocked)
			{
				// Add the item to the List & list view
				GlobalVals.dwgs.Add(dwgEntry);
				AddListViewItem(dwgEntry);
			}
			else
			{
				// Some or all of the PDFs are locked
				foreach (string error in FileOps.WhichPDFsAreLocked(dwgEntry))
				{
					errors.Add(error);
				}
			}
		}
		else if (dwgEntry.IsDWGLocked)
		{
			errors.Add("The drawing " + dwgEntry.DWGName + " is currently open by a user.");
		}
	}
	else
	{
		errors.Add("The drawing " + Path.GetFileName(dwg) + " is already in the list.");
	}
}

 

 

I tried doing it in parallel here, which crashed my AutoCAD:

 

Parallel.ForEach(dialog.FileNames,  (dwg) = >
{
	// Same body code as above
}

 

 

Later in my code, I create a consolidated DSD file from the information in DWG object and send it to the publisher.

509 Views
1 Reply
Reply (1)
Message 2 of 2

micle.space
Enthusiast
Enthusiast

just a quick result for a quick research on this forum:

 

https://forums.autodesk.com/t5/net/parallel-read-from-net/m-p/6397148 

some quoted text: "...There is no parallel processing in AutoCAD.  For better performance I would first suggest... "

 

https://forums.autodesk.com/t5/net/parallel-loop/m-p/3726470 

again some quoted text: "...Sorry for the bad news, but the AutoCAD API isn't thread safe. You can.... "