.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

AcadDocument.SendCommand doesn't wait (executes asynchronously)

6 REPLIES 6
SOLVED
Reply
Message 1 of 7
Millerni456
7146 Views, 6 Replies

AcadDocument.SendCommand doesn't wait (executes asynchronously)

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

6 REPLIES 6
Message 2 of 7
FRFR1426
in reply to: Millerni456

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.

Maxence DELANNOY
Manager
Add-ins development for Autodesk software products
http://wiip.fr
Message 3 of 7
Millerni456
in reply to: FRFR1426

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.

Message 4 of 7
FRFR1426
in reply to: Millerni456

You can add an event handler to the Document.EndCommand event to wait for the end of NETLOAD execution.

Maxence DELANNOY
Manager
Add-ins development for Autodesk software products
http://wiip.fr
Message 5 of 7
Millerni456
in reply to: FRFR1426

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.

Message 6 of 7
FRFR1426
in reply to: Millerni456

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.

Maxence DELANNOY
Manager
Add-ins development for Autodesk software products
http://wiip.fr
Message 7 of 7
Millerni456
in reply to: FRFR1426

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.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost