Hi all,
I'll try to keep this breif and to the point.
I have two C# assemblies used for starting my application:
The first creates an AutoCAD instance and execute commands using COM interop.
The second is a .NET dll which has a command entry point.
The application starts up fine, but I notice I am having a synchronization issue.
Apparently, when I call AcadDocument.SendCommand( ) the function doesn't wait for my second assemply to finish.
In the second assemby, I am using WPF (Windows Presentation Foundation) in order to display a GUI, which is shown via Window.ShowDialog( ).
My expectation is that Window.ShowDialog( ) actually causes the first assembly to not finish the SendCommand( ) function. However, I am apparently wrong.
Anyways... let me get some code up here so you can visualize what is happening.
Assembly 1:
//Create AutoCAD instance, then...
acadApp.ActiveDocument.SendCommand("(command \"NETLOAD\""+@"""C:\\acad\\networkdll\\SecondAssembly.dll"") "); acadApp.ActiveDocument.SendCommand("#MYCOMMAND 0 ");
//Close the startup drawing (this requires waiting @ SendCommand) because
//Drawing will cause a COMException otherwise. 'Drawing is busy'
//Mostly likely since the ActiceDocument is the startup drawing.
Assembly 2:
[CommandMethod("#MYCOMMAND", CommandFlags.Session)] public void CommandEntry() {
//Process command argument, then...
//Create window.
MainWindow mainWin = new MainWindow();
mainWin.ShowDialog(); }
Instead of the applicating waiting for SendCommand( ) to finish, it ends up hanging at the entry of a foreach loop (makes absolutely 0 sense to me). The loop is used for interating through the document list in order to find the startup drawing.
Well, am I stuck? Does anyone know if there is a way to synchronize this in a better way?
As a desparation, I could create a lock file I suppose in order to determine when to continue processing; that is a workaround however.
Anyways, I greatly appreciate those of you who spend your time helping an random person over the internet.
Thanks and God bless!
Nicholas Miller
Solved! Go to Solution.
Solved by Millerni456. Go to Solution.
Solved by FRFR1426. Go to Solution.
I think it's because you are using the Session flag on your #MYCOMMAND command. You're then in application context and SendCommand can not run synchronously.
Hi FRFR1426,
That could be the cause. However it is essential to be in session mode since the window that appears is responsible for allowing the user to automatically modify sets of drawings.
You can add an event handler to the Document.EndCommand event to wait for the end of NETLOAD execution.
Hm, I'm trying to see how that solves this. The NETLOAD is required for loading a .DLL, while the #MYCOMMAND executes a function in the .DLL.
My understanding is that NETLOAD is fine. I need to perform a blocking wait after I execute #MYCOMMAND, since Session Mode causes it to be asynchronous.
On an interesting side note, this adndevblog says it should be synchronous the way I'm attributing the command function:
http://adndevblog.typepad.com/autocad/2012/05/why-does-sendcommand-run-asynchronously.html
I'm using AutoCAD 2012 if that affects anything.
If you are in the application context (with session flag on), SendCommand should execute synchronously. But may be it will not be synchronous if you're calling for user interaction (Editor.Getxxx methods or ShowDialog...) in your command. Just use CommandEnded event and wait for the end of your #MYCOMMAND command.
Ha! It worked!
Thanks much! 🙂 🙂
I'm using System.Threading.EventWaitHandle for blocking.
Here is what the new code looks like:
//Create AutoCAD instance, then... acadApp.ActiveDocument.SendCommand("(command \"NETLOAD\""+@"""C:\\acad\\networkdll\\SecondAssembly.dll"") "); acadApp.ActiveDocument.SendCommand("#MYCOMMAND 0 ");
//Register EndCommand handler. _DAcadApplicationEvents_EndCommandEventHandler handler = new
_DAcadApplicationEvents_EndCommandEventHandler(CommandEnded);
acadApp.EndCommand += handler;
waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
waitHandle.WaitOne();
acadApp.EndCommand -= handler; //Close the startup drawing (this requires waiting @ SendCommand) because //Drawing will cause a COMException otherwise. 'Drawing is busy' //Mostly likely since the ActiceDocument is the startup drawing.
Event Handler:
public void CommandEnded(string globalCommandName) { System.Windows.MessageBox.Show(globalCommandName + " just ended."); waitHandle.Set(); }
The second assembly was left unchanged.
While tinkering, I confirmed that using 'session lock files' to perform blocking works.
In Assembly 1 create a lock file, then wait as long as the file exists.
In Assembly 2 delete the file when required.