Executing delegate in a different thread
-
I have a problem while trying to execute a delegate in a different thread. I have my application and autocad that has loaded my .net-dll. I created a named-pipe-server (in an own thread in the dll for autocad) and send messages to it from my application. The thread with the server watis for the messages and executes a delegate on receiption. The method in my class (in the dll) is called and I can show it with a messagebox. Till here everything is fine. But now I want to open a new file for autocad and I try to use the regarding method-call (AcadApp.Application.DocumentManager.Open(file)). But here is the problem. I get an exception about internal error or wrong context. I'm still in the thread-context of my listening server and I think that is the problem. But how can I execute a function in the autocad-thread? My initialization-function that creates the listening-thread is executed in the autocad-thread-context so I can get Thread-object or whatever is needed.
-
I have a problem while trying to execute a delegate in a different thread. I have my application and autocad that has loaded my .net-dll. I created a named-pipe-server (in an own thread in the dll for autocad) and send messages to it from my application. The thread with the server watis for the messages and executes a delegate on receiption. The method in my class (in the dll) is called and I can show it with a messagebox. Till here everything is fine. But now I want to open a new file for autocad and I try to use the regarding method-call (AcadApp.Application.DocumentManager.Open(file)). But here is the problem. I get an exception about internal error or wrong context. I'm still in the thread-context of my listening server and I think that is the problem. But how can I execute a function in the autocad-thread? My initialization-function that creates the listening-thread is executed in the autocad-thread-context so I can get Thread-object or whatever is needed.
-
You can try using MethodInvoker inside your thread to invloke the function in another thread.
Thanks Laddie Kindly rate if the answer was helpful
How does it work? Can you give me a sample? As you see I tried something but it doesn't work. my code:
class IPCMsgHandler
{
private Thread listenThread = new Thread(ListeningThreadFunc);...
public void Start() { listenThread.Start(this); } private static void ListeningThreadFunc(object data) { IPCMsgHandler helper = data as IPCMsgHandler; ... //helper.OnMessage(); doesn't work...staying in current thread context MethodInvoker mi = new MethodInvoker(helper.OnMessage); mi.Invoke(); ... }
}
public class AutoCADApplication : IExtensionApplication
{
IPCMsgHandler helper = null;public void Initialize() { // I have the right execution-context here this.helper = new IPCMsgHandler("AutoCAD-IPCServer", new IPCMsgHandler.MessageHandler(this.OnIPCMessage)); this.helper.Start(); } private void OnIPCMessage() { // I have the WRONG execution-context here return; }
-
How does it work? Can you give me a sample? As you see I tried something but it doesn't work. my code:
class IPCMsgHandler
{
private Thread listenThread = new Thread(ListeningThreadFunc);...
public void Start() { listenThread.Start(this); } private static void ListeningThreadFunc(object data) { IPCMsgHandler helper = data as IPCMsgHandler; ... //helper.OnMessage(); doesn't work...staying in current thread context MethodInvoker mi = new MethodInvoker(helper.OnMessage); mi.Invoke(); ... }
}
public class AutoCADApplication : IExtensionApplication
{
IPCMsgHandler helper = null;public void Initialize() { // I have the right execution-context here this.helper = new IPCMsgHandler("AutoCAD-IPCServer", new IPCMsgHandler.MessageHandler(this.OnIPCMessage)); this.helper.Start(); } private void OnIPCMessage() { // I have the WRONG execution-context here return; }
Hi, You need a reference to a control that has a window handle associated with it (something that inherits from System.Windows.Forms.Control) and lives on the Autocad main thread. Possibly you can get that through the Autocad API (with which I'm not at all familiar). If you have that reference in a variable called
control
you invoke your delegate withcontrol.Invoke(mi)
instead ofmi.Invoke()
. This routes the invocation through the event queue on the UI thread, which should solve your problem. Assuming you can get your hands on a suitable Control object of course...-- Peter
-
Hi, You need a reference to a control that has a window handle associated with it (something that inherits from System.Windows.Forms.Control) and lives on the Autocad main thread. Possibly you can get that through the Autocad API (with which I'm not at all familiar). If you have that reference in a variable called
control
you invoke your delegate withcontrol.Invoke(mi)
instead ofmi.Invoke()
. This routes the invocation through the event queue on the UI thread, which should solve your problem. Assuming you can get your hands on a suitable Control object of course...-- Peter
That would work for a windows forms based API, and although I don't know the Autocad API either I wouldn't expect it to be Forms based. A better bet might be to implement a producer/consumer type of architecture[^].
Standards are great! Everybody should have one!
-
That would work for a windows forms based API, and although I don't know the Autocad API either I wouldn't expect it to be Forms based. A better bet might be to implement a producer/consumer type of architecture[^].
Standards are great! Everybody should have one!
True... but the API might contain something similar. I'd look around for a method called
Invoke()
on objects exposed by it. That mechanism isn't specific toWindows.Forms.Control
, but to theSystem.ComponentModel.ISynchronizeInvoke
interface, which is implemented by controls. Chances are that there is something similar available (there should be, if cross-thread calls are an issue). However... I don't seem to remember the "wrong execution context" error message from inadvertently doing cross-thread method invocations in Windows.Forms. This could be something completely different. If it has anything to do with aSystem.Threading.ExecutionContext
, there is something seriously broken in AutoCAD or its API. In the code presented, theOnIPCMessage()
method shouldn't care less about from which thread it is invoked, and even if it did, theExecutionContext
should be just fine (it gets copied when the managed thread is started). Or could it be that the code causing the problem isn't included in the post? Nite!-- Peter