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();
Related
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.
I've made a sample program which generates every second 2000 integers on a Background thread, and when it finishes it fires an event which draws graph on the GUI from the random generated data (I have a sleep inside my thread to simulate a real measurement).
private void SetChart(System.Windows.Forms.DataVisualization.Charting.Series series)
{
if (InvokeRequired)
{
SetChartCallback d = new SetChartCallback(SetChart);
this.Invoke(d, new object[] { series });
}
else
{
chart1.Series[0] = series;
chart1.Series[0].Name = "Generated Data";
}
}
I found this approach on the MSDN site. It's working fine, the only problem is, when I close the application. Sometimes an error meassage shows up :
Cannot access a disposed object.
Object name: 'Form1'.
When I close the program it disposes all the elements, how can I prevent this error not to happen?
You've closed the form, but the thread is still running, so when it completes It tries to invoke a method on the disposed object. Your form.
You can wait for the thread to complete.
Or you can signal it somehow to stop messing about creating integers you don't need anymore and quit it's loop right now.
Don't be tempted to just kill it. Very bad habit, you don't want get into that.
The proper approach, ugly as it may seem, is probably to catch the exception and swallow it. It's probably not reasonable for the form's Dispose to block until the background thread exits (a situation which could easily cause deadlock); nor does the Framework provide any method which says try to Invoke or BeginInvoke this method on a control or form, but simply do nothing if it's been disposed. Thus, your best bet is probably to write TryInvoke and TryBeginInvoke methods which will do that by catching any exception that results if the form has been disposed. You might use an IsDisposed check within such a method, but you should realize that because of some Framework quirks, there are some race conditions which cannot be resolved nicely.
A solution may be to check IsDisposed. Something like this:
private void SetChart(System.Windows.Forms.DataVisualization.Charting.Series series)
{
if (IsDisposed)
return;
// ...
}
I'm using the following method to show a modeless Message Box.
public void ShowMessageBox(string Message)
{
var thread = new Thread(
() =>
{
MessageBox.Show(Message);
});
thread.Start();
}
The "() => {...}" is something I've never seen before. What is the name for this code pattern?
Also, thread.Start starts the thread, and it automatically closes once the "()=>{...}" method completes (when the Message Box is OK'ed), right? If so, can you please point me to some official documentation saying that the thread closes automatically?
Thanks!
It's the lambda operator, and read as "goes to". MSDN has a good intro: Lambda Expressions (C# Programming Guide)
One concern with your example is that you're spinning up a new thread to update the UI, the UI is intrinsically single-threaded, so background updates are generally the wrong thing to do (unless you're manually/explicitly checking InvokeRequired and calling Invoke() as needed.
Regarding the UI threading...
In WinForms every Form or Control is created on a particular thread (the "UI Thread"), and you can think of that thread as owning that control (not exactly correct, but a good way to conceptualize it). Updating the UI from that thread is safe, updating the UI from another thread runs the risk of collisions and corruption and all the usual risks of parallel/async programming.
...So... how do you safely update the UI from a background thread without blocking the UI? In short--you can't--the best you can do is block it for the bare minimum required to update the UI. This is where InvokeRequired and Invoke() come in...
Here's a sample: you should be able to drop this into the code-behind of a new form with a button and textbox.
To use:
Try commenting out either the call to SetTextAsyncSafe() or SetTextAsyncSafe() -- running both could confuse you since they won't necessarily execute in the order they're called (they're running async, remember?).
Then set a breakpoint on SetText(). You should see the "safe" call will actually call the method twice--the first call will detect InvokeRequired and will call the method a 2nd time for the correct thread by Invoke()'ing to it.
You should see an Exception thrown when SetTextAsyncUnsafe() actually gets to the textBox1.Text = value; statements. The exception will be an InvalidOperationException with a message stating "Cross-thread operation not valid" -- you can google this term for more details.
The code:
private void button1_Click(object sender, EventArgs e)
{
SetTextAsyncSafe("This update was made from the UI Thread by using Invoke()");
SetTextAsyncUnsafe("This update was made directly from the background thread and can cause problems");
}
private void SetTextAsyncUnsafe(string value)
{
new Thread(() => SetText(value, false)).Start();
}
private void SetTextAsyncSafe(string value)
{
new Thread(() => SetText(value, true)).Start();
}
private void SetText(string value, bool checkInvokeRequired)
{
if (checkInvokeRequired)
{
if (InvokeRequired)
{
Invoke(new Action(() => SetText(value, checkInvokeRequired)));
return; // early exit
}
}
textBox1.Text = value;
}
That is a Lambda. In this case, you're using it to create a new anonymous method that will be run when the new Thread is started.
It's the (near) equivalent of:
public void ShowMessageBox(string Message)
{
var thread = new Thread(ShowBox);
thread.Start(Message);
}
public void ShowBox(object message)
{
MessageBox.Show(message.ToString());
}
This is called a Lambda Expression. You can read more here.
Lambda expression, C# version 3 feature.
Don't use this code. A message box needs a parent window, something it can make sure to be on top of. It can normally find a parent by itself by iterating the windows that were created on the same thread. Not in this case though, there are no other windows, it has to pick the desktop window as the parent.
That will go wrong badly when the user is working in an app window or switches focus to another app, the message box disappears behind the foreground window. There is no obvious way for the user to tell that it is there, she'll just loses sight of it. It could be hours, if not days, before she finds it back. That thread is meanwhile consuming resources badly, you would probably never consider it if you knew that this message box requires a megabyte of memory. In extreme cases, you'll crash the program with OOM.
The common alternative in Windows UI programming is a balloon tooltip provided by a NotifyIcon. Or your own form with the TopMost property set to True so it cannot easily get lost. Also allows you to control the position, important for "non-modal" notifications that should not get in the way. Set that form's ShowWithoutActivation property to true in the form constructor so it doesn't steal the focus.
Its a statement lambda.
Yes, thread is active as long as this anonymous method is running. Since after MessageBox.Show() there is no other statements, thread will exit, and this must be true... if you are in doubt add this before start:
thread.Name = "LALALA";
And then debug your app. When the message box apear, pause execution, go to Threads View and you will see LALALA running. Click OK and pause again, there should be no "LALALA"... =)
I have some code which is been running by a backgroundworker I'd like some specific code which shows some GUI to run in the main thread context (2 reasons 1. it should be blocking 2.I know it's problematic to handle gui controls from a background worker)
I raise an event pass the class and listen to the event in the mainForm from there I check if invoke required and reinvoke. then call the public method of the instance I want to run in the main thread. I have a few questions:
is there any problem to handle data member which are created in the backgoundworker context from the main thread - for both reading and chaning valuse
is there any design pattern for such issue? Idealy I'd like to run any delegate- any return value and a few genric parameters- as func built in delegate- that is problematic because It means if I want to support up to 3 parameters with or without return values I'll have to have 6 events and 6 listeners which actually do the same - does anyone have an idea of how to do this correct?
Thanks!
I just wrote this for a similar question.
I use threads for these kind of stuff.
somewhere in my code:
// Definition
private static Thread TH;
....
// When process starts
TH = new Thread(new ThreadStart(Splash_MyCallBack));
TH.Start();
....
// This method starts the form that shows progress and other data
static private void Splash_MyCallBack()
{
frmLoading FL;
FL = new frmLoading();
FL.ShowDialog();
} /* Splash_MyCallBack*/
// Your process calls Splash_Stop when it is done.
static public void Splash_Stop()
{
TH.Abort();
} /* Splash_Stop*/
frmLoading performs the visual stuff, while in the background I have a very processor-intensive task.
My process reports to an interface its progress. frmLoading implements that interface so it is aware of it and can show whaever it is needed (2 progress bars in my case)
Tha only catch is, frmLoading must have this in the constructor:
Control.CheckForIllegalCrossThreadCalls= false;
which may be risky in some scenarios (not my case).
I think that the fact that the main process calls an interface to update progress, and the real interface consumes that is a pattern.
Hope this helps, I can add more stuff if you like.
Regards,
To answer your first question:
There shouldn't be any problems handling data created in the background worker. I've done it in a couple of applications and not had any issues.
I was testing a program I am writing and I got this error message: Cross-thread operation not valid: Control 'lblStatus' accessed from a thread other than the thread it was created on
The code is a bit massive and I am not sure which part is causing this error to post a smaller segment. However here is some info that might be of use.
I am not using any "threading" explicitly. I am guessing something else is automatically creating multiple threads - I am using a Wii remote hardware access library and I am doing graphics manipulation.
The stack trace indicates, that a call is made to an on change event handler, which calls a function inside which lblStatus is tried to be modified - but fails.
I was wondering how do you debug these types of errors. I am using Visual Studio 2008.
EDIT
One thing I want to clarify, I do not know how this different thread even came up. How would I even find this? the source of the different thread.
public void SetStatus(string msg)
{
if (lblStatus.InvokeRequired)
lblStatus.Invoke(new MethodInvoker(delegate
{
lblStatus.Text = msg;
}));
else
lblStatus.Text = msg;
}
This will get your label text updated.
For a BeginInvoke, this is the way I know (I know there are more elegant implementations) - but I haven't tried this in a multi-threaded app yet:
Action<string> setStatus= target.AppendText;
void OnSomeEvent (object sender, EventArgs e)
{
IAsyncRes iares = setStatus.BeginInvoke("status message", null, null);
setStatus.EndInvoke(iares);
}
public void SetStatus(string msg)
{ lblStatus.Text = msg; }
For the different methods of synchronizing to the control thread, SnOrfus references an excellent link. My example above on BeginInvoke is not correct for synchronizing to the control's thread.
As far as what is causing the thread: About WiimoteChanged event
You can't access visual elements from any thread other than the main thread. You need to use Dispatcher.Invoke() to call a delegate which updates the visual elements.
Example:
this.Dispatcher.Invoke((Action)(() => lblStatus.Content = "Hello"));
or (without lambda):
this.Dispatcher.Invoke((Action)delegate() { lblStatus.Content = "Hello"; });
You need to combine the use of Delegates with your threads..
Assign your method to a delegate and then invoke the delegate through thread.
One thing I want to clarify, I do not know how this different thread even came up
If your app is not multithreaded, the problem could be caused by the Visual Studio hosting process. The Visual Studio hosting process starts up a main thread and then creates a new UI thread that the application is run on. In some circumstances this can lead to a cross-thread exception, for example when accessing Form.ActiveForm before calling Application.Run.
If this is your problem, you can uncheck "Enable the Visual Studio hosting process" in the Debug tab of Project Properties.