I have an external component (C++), which I want to call from my C# code.
The code is something like this:
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace dgTEST
{
class Program
{
[STAThread]
static void Main(string[] args)
{
ExtComponentCaller extCompCaller = new ExtComponentCaller();
result = extCompCaller.Call(input);
Thread t = new Thread(new ThreadStart(() =>
{
try
{
result = extCompCaller.Call(input);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}));
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
}
}
}
So the problem is that, at the first call it's working well, the external component called, I got back result.
But when I try to call it in an other thread, I got an exception:
System.InvalidCastException: Unable to cast COM object of type 'System.__ComObject' ... .
I'm sure this exception throwed, because of the STAThread. Because if I remove the [STAThread] attribute from the Main function, the same occurs with the first call of the external component, which was worked fine.
How can I call this external component from an other thread to get rid of this exception?
UPDATE-------------
Other crazy thing occurs now. When I start the program from Visual Studio with F5, the problem occurs in the first call as well, but when I execute directly the binary .exe file, it's working (from the other thread it isn't :( ).
If I switch the build from Debug to Release and starting it from Visual Studio with F5, the first call working again.
Why does it happen?
Thanks for you help in advance!
Best Regards,
Zoli
Threading is never a small detail. If code isn't explicitly documented to support threading then the 99% odds are that it doesn't support it.
And clearly this component doesn't support threading. Creating another STA thread is not the magic solution, it is still a different thread. The InvalidCastException tells you that it also is missing the proxy/stub support that's required to marshal calls from a worker thread, like the one that you are trying to create. Required to make thread-safe calls to code that isn't thread-safe. Albeit that you did break the contract for an [STAThread], it must pump a message loop. It is the message loop that allows making calls from a worker thread to a component that isn't thread safe. You get a message loop from Application.Run().
This is where the buck stops. It isn't thread-safe, period. Even if fix your main thread or ask the vendor or author to supply you with the proxy/stub, you still haven't accomplished what you set out to do, it won't actually run on that worker thread you created. So it must look like this:
static void Main(string[] args)
{
Thread t = new Thread(new ThreadStart(() =>
{
ExtComponentCaller extCompCaller = new ExtComponentCaller();
result = extCompCaller.Call(input);
}));
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
}
Which creates the object on the same thread that you make the calls from so it is thread-safe. There's still the problem that this worker thread doesn't pump a message loop, COM components tend to rely on that. You'll find out whether that's a problem or not from deadlock or events that don't run. If it already worked okay in your test program when you called it from the main thread then you are probably okay with not pumping.
Related
I have a project in Xamarin.IOS which interacts with a UI component via NSEvents. UI sends messages through events with a payload - google's protobuf encoded objects. UI is written in ObjC, the logic is written in C#.
Each NSEvent is caught in an observer that invokes internal logic which begins the processing of a message. These messages are put into a queue and eventually taken by threads from the queue.
When a message arrives, the program can create a thread for it, and that's the place where it fails. The code is legacy, so we are using Thread. I write
Thread t = new Thread(ThreadProc);
t.IsBackground = true;
t.Start();
The code used to work a short while ago, also it works sometimes. Sometimes the thread is simply not created. No error is reported.
If I create a thread not in a context of an observer, the thread is started.
I have no idea why it may happen. The problem arises in the very initialization of the application, when the first thread is about to be created. So I don't think there are too many threads.
I have tried to re-create it with Task interface. Tasks are created and started alright, but I can not migrate entire solution to Tasks, unfortunately.
I guess there is some configuration issue or like that since it used to work. I just don't get what it might be. What can affect Thread.Start()?
UPD: I've rolled back to a very old commit which used to work, now it fails too. So it seems not to be a configuration issue, but ios/xamarin issue.
I've never seen anything remotely similar (creating and starting a Thread not actually doing anything), so my first thought is to ensure that this code is actually executed in the first place.
Can you add a Console.WriteLine statements like this:
Console.WriteLine ("creating thread");
Thread t = new Thread(() =>
{
Console.WriteLine ("executing ThreadProc");
try {
ThreadProc ();
} finally {
Console.WriteLine ("finished executing ThreadProc");
}
});
t.IsBackground = true;
t.Start();
Console.WriteLine ("started thread");
and then see what actually shows up in the application output?
I am working on understanding how to use BeginInvoke correctly. I wrote up a small test in a console app where all I am trying to do is use BeginInvoke to call a function to make a 100x100 Window with a title pop up. I am failing miserably. Here is what I have, I know this is probably just poor understanding of Threads (not my strong suit), but I'm stuck, no window pops up I just end up at my readline in Main waiting for a keypress. Execution starts at ThreadUITest.
static void ThreadUITest()
{
ThreadStart starter = new ThreadStart(threadFunc1);
Thread test = new Thread(starter);
test.IsBackground = true;
test.SetApartmentState(ApartmentState.STA);
test.Start();
}
static void threadFunc1()
{
dispatcher = Dispatcher.CurrentDispatcher; //Statically declared earlier
ThreadStart starter = new ThreadStart(threadFunc2);
Thread test = new Thread(starter);
test.IsBackground = true;
test.Start();
}
static void threadFunc2()
{
Action method = Draw;
Console.WriteLine("I'm here!");
//dispatcher.BeginInvoke( (Action)(() => {Draw();}),DispatcherPriority.Render, null);
dispatcher.BeginInvoke(method, DispatcherPriority.Send, null);
}
static void Draw()
{
Window win = new Window();
win.Height = 100;
win.Width = 100;
win.Title = "A Window!";
win.Show();
}
Thanks for any help.
You need to add the following at the bottom of your threadFunc1
// statically declared earlier, although you don't need to keep a reference to it as
// WPF will keep it in Application.Current
application = new Application();
application.Run(); // thread1 is now our "UI" thread
Why does this solve it?
The Dispatcher object provides an interface for getting a thread to do some work for you (via BeginInvoke or Invoke).
In order for a thread to be able to process any "do work" messages, it must be running some kind of event loop, where it sits and waits for the next message to process - if it weren't doing this, then it wouldn't be able to process anything, it would just be stuck.
Calling Dispatcher.CurrentDispatcher from thread1 will create a new dispatcher on that thread if there isn't one already there[1] - that gives us our interface to post messages to the thread.
What dispatcher.BeginInvoke does is add an entry into the message queue for that thread, however the thread isn't running any message loop yet. We can queue messages to it, but it won't pick them up and run them - this is why nothing happens.
So, we need to make that thread start running a message loop.
The Application.Run() method is the WPF framework method which does exactly that. The Application.Run method never returns (until you call Application.Shutdown anyway), it starts up a message loop to begin processing messages thereafter. I find it useful to think of it "taking over" the thread.
Now with this change, when thread2func calls dispatcher.BeginInvoke, the message loop code inside Application.Run goes "oh look, a message, I'll process it" - it gets the BeginInvoke method, and does what it's told (in this case, executing your Draw function), and all is well
Note: As per Ark-kun's answer You can also just call Dispatcher.Run to start a message loop on that thread without creating an Application object (Application.Run does this internally). Generally I find it nicer to create an application object though, as that's more "normal", and some other code you may write later on may expect an Application object to exist
[1] FYI, this is why calling Dispatcher.CurrentDispatcher is dangerous and you should avoid it. If you call Dispatcher.CurrentDispatcher from the existing UI thread, it returns you a reference to the correct dispatcher.
If you accidentally call it from another thread, logically, you'd think it would return a reference to the existing dispatcher. But no - instead, it creates a second dispatcher, pointing at our other thread - however our other thread won't be running a message loop, and we'll get stuck again. I'd suggest never calling Dispatcher.CurrentDispatcher except for the very first time.
Once your app is up and running, you generally don't need to do this anyway, as all WPF objects (Window, Button, etc) all have a Dispatcher property which you can use to get the correct dispatcher from anyway
Try calling Dispatcher.Run() in the end of threadFunc1.
I have a WPF application which uses some library code for authentication which needs to run in a Single-Thread Apartment thread. My approach is to spawn a separate thread to get the authentication object, block until the thread returns and then continue execution. However, in some instances my application hangs on Thread.Join(), even though the thread method has returned.
public static ClaimsAuthenticationResult GetClientContextAndCookieCollection(string siteUrl, out CookieCollection cookieResult)
{
ClaimsAuthenticationResult authResult = new ClaimsAuthenticationResult();
// Authentication module needs to run in single-thread apartment state because it uses
// COM library calls where this is required
Thread authenticationThread = new Thread(new ThreadStart(threadMethod));
authenticationThread.SetApartmentState(ApartmentState.STA);
authenticationThread.Start();
// Block until thread completion
authenticationThread.Join(); // Application hangs here
return authResult;
}
private static void threadMethod() {
// In proper application: set result. But for debugging, return immediately
return;
}
I am new to both mulththreading and WPF, so I might be doing something stupid. Does anyone see what's going on here? For the record, I don't get the problem if I don't set the thread to STA, but this is a requirement.
[Edit: It appears that the error only occurs when I call the specified method through a validation binding in a WPF view, specifically on a TextBox. When I call the same code in the constructor of the view, the code runs as expected. This would be a viable workaround, but it would be interesting to know what's actually going on here.]
[Edit: The code here has been simplified a bit for debugging - in the production code, the thread method is inside an AuthThreadWorker object which enables returning the result of the authentication process to the authResult object. But these details are as far as I can tell unrelated to the freeze, as the freeze occurs even in the simplified code.]
Based on your code; it looks as if you're doing it correctly, but the thread is never REALLY terminating. Try setting a breakpoint at the END of the function in the thread; instead of the return keyword (in case you're doing some kind of processing in your return statement that prevents the thread from exiting), as shown in the picture below
. Naming the thread using authenticationThread.Name (or mthread.Name as shown in example) can also aid with debugging. If the thread REALLY terminated, you should see "The thread 'yourname' (0x143c) has exited with code 0 (0x0)." in the Output window of Visual Studio.
I'm using a COM object from a third party library that generates periodic events. When I use the library from a Winforms app, having the object as a class member and creating it in the main form thread, everything works. However, if I create the object from another thread, I don't receive any event.
My guess is that I need to have some kind of event loop in the same thread used to create the object.
I need to use this object from a console application. I guess I could use Application.DoEvents, but I'd rather not include the Winforms namespace in a console App.
How can I solve this problem?
Update 3 (2011-06-15): The vendor has answered at last. In short, they say there is some difference between the message pump created by Application.Run and the one created by Thread.Join, but they don't know what that difference is.
I agree with them; any light shed on this matter would be very appreciated.
Update:
From Richard comment to mdm answer:
if there other component is single threaded and instantiated from an MTA then Windows will create the worker thread + window + message pump and do the necessary marshalling.
Trying to follow his advice, I'm doing the following:
Update 2:
I'm changed the code following João Angelo answer.
using System;
namespace ConsoleApplication2
{
class Program
{
[STAThread]
static void Main(string[] args)
{
MyComObjectWrapper wrapper = new MyComObjectWrapper();
}
}
class MyComObjectWrapper
{
MyComObject m_Object;
AutoResetEvent m_Event;
public MyComObjectWrapper()
{
m_Event = new System.Threading.AutoResetEvent(false);
System.Threading.Thread t = new System.Threading.Thread(() => CreateObject());
t.SetApartmentState (System.Threading.ApartmentState.STA);
t.Start();
Wait();
}
void ObjectEvt(/*...*/)
{
// ...
}
void Wait()
{
m_Event.WaitOne();
}
void CreateObject()
{
m_Object = new MyComObject();
m_Object.OnEvent += ObjectEvt;
System.Threading.Thread.CurrentThread.Join();
}
}
}
I have also tried the following instead:
public MyComObjectWrapper()
{
CreateObject();
}
If you're using STA, then you're going to need a message loop one way or another. If you don't otherwise need a message loop, MTA is perhaps the simplest way to go, and is also the best for for a console-style application.
One thing to be aware of is that with MTA, it doesn't matter which thread created the object; all objects created by an MTA thread belong equally to all MTA threads. (Or, in COM speak, a process has exactly one Multi-Threaded Apartment, in which all MTA threads live.) What this means is that if you're taking the MTA approach, there's no need to create a separate thread at all - just create the object from the main thread. But you also need to be aware that incoming events will be delivered on a 'random' thread, so you'll have to take separate steps to communicate back to the main thread.
using System;
using System.Threading;
class Program
{
static MyComObject m_Object;
static AutoResetEvent m_Event;
[MTAThread]
static void Main(string[] args)
{
m_Event = new AutoResetEvent(false);
m_Object = new MyComObject();
m_Object.OnEvent += ObjectEvt;
Console.WriteLine("Main thread waiting...");
m_Event.WaitOne();
Console.WriteLine("Main thread got event, exiting.");
// This exits after just one event; add loop or other logic to exit properly when appropriate.
}
void ObjectEvt(/*...*/)
{
Console.WriteLine("Received event, doing work...");
// ... note that this could be on any random COM thread.
Console.WriteLine("Done work, signalling event to notify main thread...");
m_Event.Set();
}
}
Couple of comments on the previous version of the code you had: you had calls to Wait() in both CreateObject and in the MycomObjectWrapper constructor; seems you should only have one - if you have two of them, only one of them will get released when m_Event.Set() is called, and the other will still be waiting. Also, suggest adding in some debugging code so you know how far you are getting. That way you can at least tell if you are getting the event from COM, and separately, whether you are successfully communicating that back to the main thread. If the objects are marked neutral or both in the registry, then there should be no problem creating them from a MTA.
As already stated in other answers STA COM components require a message loop to be run in order for calls happening in other threads be correctly marshaled to the STA thread that owns the component.
In Windows Forms you get the message loop for free, but in a console application you must do it explicitly by calling Thread.CurrentThread.Join on the thread that owns the COM component and that is probably also the main thread for the application. This thread must be STA.
From the MSDN entry of Thread.Join you can see that this is what you want:
Blocks the calling thread until a thread terminates, while continuing to perform standard COM and SendMessage pumping.
If you don't want to do anything else in the main console thread you just wait indefinitely, otherwise you can do other stuff while periodically calling Thread.CurrentThread.Join to pump messages.
Side-note: This assumes you're dealing with a STA COM component.
A simplified example:
class Program
{
[STAThread]
static void Main(string[] args)
{
var myComObj = new MyComObject();
myComObj.OnEvent += ObjectEvt;
Thread.CurrentThread.Join(); // Waits forever
}
static void ObjectEvt(object sender, EventArgs e) { }
}
In this example the console application will be in a never ending loop that should do nothing more then respond to events from the COM component. If this does not work you should try to get support from the COM component vendor.
IIRC, COM events require an event loop to work, something that pumps messages and calls the Win32 GetMessage function.
Winforms does this for you, or you can emulate it with Win32 calls. This question/answer has a good example you can build on.
I think the following should work:
[STAThread]
Main(...)
{
var comObject = new YourComObject();
comObject.Event += EventHandler;
Console.WriteLine("Press enter to exit.");
Console.ReadLine();
}
void EventHandler(...)
{
// Handle the event
}
Have you defined the thread apartment model?
[STAThread]
static void Main(string[] args)
{
// Create the thread that will manage the COM component
Thread th = new Thread(...);
// Before starting the thread
th.SetApartmentState (ApartmentState.STA);
}
In the thread, just wait for an Event to signal its termination. While the thread is waiting on the event, I think that it should process messages on the thread loop.
Could you try this:
static class Program
{
MyComObject m_Object;
[STAThread]
static void Main()
{
m_Object = new MyComObject();
m_Object.OnEvent += ObjectEvt;
System.Windows.Forms.Application.Run();
}
void ObjectEvt(/*...*/)
{
// ...
}
}
System.InvalidOperationException: DragDrop registration did not
succeed. ---> System.Threading.ThreadStateException:
What does this exception mean? I get it at this line trying to add a panel to a panel at runtime...
splitReport.Panel1.Controls.Add(ChartPanel);
Working in VS2008 C#
This exception means that the thread that owns the Panel (the Panel being added) has been initialized using the MTA threading model. The drag/drop system requires that the calling thread use the STA thread model (particularly it requires that COM be initialized via OleInitialize). Threading models are an unfortunate vestige of COM, a predecessor of the .NET platform.
If you have the [STAThread] attribute on your Main function, then the main program thread should already be STA. The most likely explanation, then, is that this exception is happening on a different thread. Look at the Threads window in Visual Studio (Debug | Windows | Threads) when the exception occurs and see if you are on a thread other than the main thread. If you are, the solution is probably as simple as setting the thread model for that new thread, which you can do as follows (add this code to the thread where the control is being created):
Thread.CurrentThread.SetApartmentState( ApartmentState.STA )
(Thread and ApartmentState are members of System.Threading)
That code will need to happen before you actually start the new thread. As noted by #Tomer, you can also specify this declaratively using the [STAThread] attribute.
If you find that the exception is happening on the main thread, post back and let us know, and maybe we can help more. A stack trace at the time of the exception may help track down the problem.
function abc
{
Thread t = new Thread(new ThreadStart(xyz));
t.SetApartmentState(ApartmentState.STA);
t.Start( );
}
function xyz
{
the code of Windows form..or whatever which is causing the error
}
Add the STAThreadAttribute attribute on the Main method. This attribute is required if your program access OLE related functions, like Clipboard class does.
[STAThread]
static void Main(string[] args)
{
}
I'm not sure whether you have solved this problem or not. I just encountered this problem and I fixed it by deleting my bin directory.
Yes, I realize this question was asked 2 and a half years ago. I hit this exception and did some reading on it. I corrected it, but didn't see my solution anywhere, so I thought I'd post it somewhere someone else could read.
One possibility for this happening with [STAThread] marked on the Main() is if you're running this on a thread other than the one you started on.
I just ran into this exception when trying to create and show a new form in a BackgroundWorker.DoWork method. To fix it, I wrapped the creation and showing of my new form into a method, and then called Invoke on that method so that it fired on the UI thread. This worked because the UI thread started from the Main() method with [STAThread] marked, as other answers here explained.
This error also can happen, if you have async Task signature on your Main()
[STAThread]
static async Task Main()
{
}
if it's feasible change it back to void
[STAThread]
static void Main()
{
}
By far the easiest way is:
private void DoSomethingOnGui()
{
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
Safe_DoSomethingOnGui();
});
}
else
{
Safe_DoSomethingOnGui();
}
}
private void Safe_DoSomethingOnGui()
{
// Do whatever you want with the GUI
}
You can even pass things along no problem:
private void DoSomethingOnGui(object o)
{
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
Safe_DoSomethingOnGui(o);
});
}
else
{
Safe_DoSomethingOnGui(o);
}
}
private void Safe_DoSomethingOnGui(object o)
{
// Do whatever you want with the GUI and o
}
I solved this error by using below code...I were using Background Worker and trying to access UI while background worker..that is why getting error - DragDrop registration did not succeed.
We cannot access UI from the code running in background worker or in thread.
BeginInvoke((MethodInvoker)delegate
{
//write your code here...
});
Thanks Happy Coding... :
I found this error, and the one that makes the error shown was when we have another thread calling MessageBox.Show(this, ...). However, this is not done initialized.
We need to remove the owner of the message box to remove the error.
"Crypto Obfuscator For .NET" can also trigger this exception, in my case the DragDrop event was subscribed to (from designer), but contained no code as I commented it out much earlier on. It took a while to figure out what is was, and this was after changing every single Obfuscator config option 1 after the next.. it came down to exactly this. If you encounter this with a popular obfuscation tool, keep this in mind.
I have encountered this situation recently,[STAThreadAttribute]is in my case,and i solved this problem by using Invoke method,it might be helpful for you guys,so I share with a little code snippet:
this.Invoke(new InvokeHandler(delegate()
{
//Your method here!
}));
And InvokeHandler is a delegate like this:
private delegate void InvokeHandler();