I used a WebBrowser control to navigate to the login page for a WordPress blog.
The page loads fine but whenever I try to access the WebBrowser from a thread. I get a specific cast is not valid exception. Also when debugging, everything freezes up for around 5 seconds. When debugging and I try to access the control. I get timed out errors on all of the member variables.
//in constructor of main form
Thread.CurrentThread.ApartmentState = ApartmentState.STA;
this.CheckForIllegalCrossThreadCalls = false;
mainThreadHandle = new Thread(mainThread);
mainThreadHandle.Start();
private void mainThread()
{
wbMain.Navigate("http://example.com/");
//navigating is set to false in the document complete event.
navigating = true;
while (navigating == true)
Thread.Sleep(5000);
try
{
//Where I get the issues
MessageBox.Show(wbMain.DocumentText);
}
catch (Exception e)
{
}
Thread.Sleep(1000);
}
WebBrowser is a COM component under the hood. An apartment threaded one, COM takes care of calling its methods in a thread-safe way. Your Navigate() call works for that reason, it is actually executed on the UI thread. What doesn't work is the DocumentText property, it is implemented in the .NET wrapper and they somewhat fumbled the code. It bombs when the COM interop support in the CLR notices that a thread in the MTA tries to access a property of a component that lives on an STA.
Your call to SetApartmentState() isn't correct. It is made on the wrong thread, the UI thread already is STA. Also the reason it doesn't bomb, you cannot change the apartment state of a thread after it is started. You must call it on the Thread object you created. It still doesn't solve your problem, two STA threads are not compatible.
Two basic ways to solve your problem. The first one is that you create the WebBrowser object itself on a separate STA thread. The code in this answer shows you how to do that.
The browser you create that way cannot also be visible on your form. Which is the second way, marshal the call yourself with Control.Invoke(). Doing this is however pretty pointless, all of your code executes on the UI thread anyway, you get no concurrency. There is no free lunch here. Running it on a thread only gives you headaches. If you need time to process the document text then run that code on a separate thread.
Why not use event model when work with WebBrowser control?
Navigating, Navigated, ProgressChanged, DocumentCompleted
Related
I have a winforms app. In development mode, when debugging from Visual Studio .NET 2003 (Yes, I know it's old, but this is a legacy project), I get this error when I try to open a new form. In order to open a new form I get an instance of the form and then I call ShowDialog() method, for example:
frmTest test = new frmTest(here my parameters);
test.ShowDialog();
If I press F11 (step into) when debugging it is not crashing, but If in the line where I instantiate the form I press F10 to go into next line, that is, test.ShowDialog(), then it crashes showing this error.
The complete message error is:
"An unhandled exception of type 'System.ApplicationException' occurred
in System.drawing.dll. Additional Information: An attempt was made to
free a mutual exclusion that does not belong to the process"
I have translated last part: Additional information ... since it was appearing in spanish.
The form that I am instantiating with parameters, its constructor, consists on initialize some variables for example:
public frmTest(string param1, string param2)
{
InitializeComponent();
this.param1 = param1;
this.param2 = param2;
}
private void frmTest_Load(object sender, EventArgs e)
{
// here I call a remote webservice asynchronously.
}
Also my form "frmTest" has four pictureboxes, a label, and a button. Three of the pictureboxes contain a png image (it is assigned on design time through Image property), the last picturebox contains a animated gif, also loaded in design time through Image property. Maybe the error occurs due to these images?
TL;DR: Your web request handler will execute on a different thread. Ensure you don't do anything that isn't thread-safe in that handler. You can use Invoke to dispatch your callback handler's code to the main thread.
Diagnosis
The problem here is almost certainly hiding in the missing details of your asynchronous call.
// here I call a remote webservice asynchronously.
Asynchronously is a little bit too vague to be sure what exactly is happening, but there's a very good chance that the asynchronous mechanism that you are using has executed its callback on a different thread from the main UI thread.
Overview
This is common in the .NET model. Asynchronous I/O in the .NET model makes use of threads in a thread pool to handle I/O via I/O Completion Ports (IOCP). It means that when a call like Socket.BeginReceive or WebRequest.BeginGetResponse (or any .NET asynchronous web request that uses similar technology internally) completes, the callback will execute on a thread in the thread pool, not the main thread. This may be surprising to you, since you didn't actively create another thread; you just participated in making asynchronous calls.
You must be very careful about what you do in the callback from your web request as many user-interface / Windows Forms operations are not permitted on any thread other than the main UI thread. Similarly, it may not be the UI itself that is causing you problems, you may have just accessed some resource or object that is not thread safe. Many seemingly innocuous things can cause a crash or exception if you're not careful with multithreading.
To resolve the issue:
If in doubt, in your callback, as early as you can, dispatch (a.k.a. Invoke) the code in your handler so that it runs on the main thread.
A common pattern for doing this would be something like what follows below.
Suppose you have made a call like this:
IAsyncResult result = (IAsyncResult myHttpWebRequest.BeginGetResponse(
new AsyncCallback(RespoCallback), myRequestState);
The handler might be set up like this:
private static void RespCallback(IAsyncResult asynchronousResult)
{
// THIS IS NOT GOING TO WORK BECAUSE WE ARE ON THE WRONG THREAD. e.g.:
this.label1.Text = "OK"; // BOOM! :(
}
Instead, dispatch any necessary processing back to the main thread.
private static void RespCallback(IAsyncResult asynchronousResult)
{
this.Invoke((MethodInvoker) delegate {
// This block of code will run on the main thread.
// It is safe to do UI things now. e.g.:
this.label1.Text = "OK"; // HOORAY! :)
});
}
I'm not advising this as a general best practice. I'm not saying to just immediately dispatch all your handlers back to the main thread. One size does not fit all. You should really look at the specific details of what you do in your handler and ensure you aren't doing thread-specific things. But I am saying that in the absence of any kind of explanation from you about what your asynchronous handlers are doing, the problem would likely be solved by invoking the handler code on the main thread.
Note: Of course, to fix your problem with this technique, it requires that your main thread is running. If you blocked your main thread with a (bad) technique like the one in this example then you'll have to redesign part of your app. Here's an example of something that would require a bigger rework:
// Start the asynchronous request.
IAsyncResult result=
(IAsyncResult) myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallback),myRequestState);
// this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted
ThreadPool.RegisterWaitForSingleObject (result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), myHttpWebRequest, DefaultTimeout, true);
// The response came in the allowed time. The work processing will happen in the
// callback function.
allDone.WaitOne(); // *** DANGER: This blocks the main thread, the IO thread
// won't be able to dispatch any work to it via `invoke`
Notice the WaitOne call? That blocks execution of the executing thread. If this code executes on the main thread, then the main thread will be blocked until the WebRequest completes. You'll have to redesign so that either you don't block the main thread (my recommendation) or that you more closely examine your callback handler to see why what it's doing is conflicting with other threads.
Application exceptions are not thrown by the framework itself: what-is-applicationexception-for-in-net; Problem should be in the code you have not the framework. Also be sure to check "InvokeRequired" property before taking the action and if it is, run the method using "Invoke" method. Can check c-sharp-cross-thread-call-problem for that.
May be the async call is trying to access UI thread.
Make sure you are not using control properties like TextBox.Text. If so, you just have to pass its value to the async call, or store it in a class variable before the call.
Also, inside an async call you can't assign values to that properties. Use Invoke() instead.
Try to add an exception breakpoint and VS will stop at the instruction causing the exception. The actual stacktrace may help.
Have You tried to close VS's local variable watch window? Maybe it is evaluating something for You on UI components where the accessing thread should be equal to owner thread of UI component!
Can anybody please explain this statement written on this link
Invoke(Delegate):
Executes the specified delegate on the thread that owns the control's underlying window handle.
Can anybody explain what this means (especially the bold one) I am not able to get it clearly
The answer to this question lies in how C# Controls work
Controls in Windows Forms are bound to a specific thread and are not
thread safe. Therefore, if you are calling a control's method from a
different thread, you must use one of the control's invoke methods to
marshal the call to the proper thread. This property can be used to
determine if you must call an invoke method, which can be useful if
you do not know what thread owns a control.
From Control.InvokeRequired
Effectively, what Invoke does is ensure that the code you are calling occurs on the thread that the control "lives on" effectively preventing cross threaded exceptions.
From a historical perspective, in .Net 1.1, this was actually allowed. What it meant is that you could try and execute code on the "GUI" thread from any background thread and this would mostly work. Sometimes it would just cause your app to exit because you were effectively interrupting the GUI thread while it was doing something else. This is the Cross Threaded Exception - imagine trying to update a TextBox while the GUI is painting something else.
Which action takes priority?
Is it even possible for both to happen at once?
What happens to all of the other commands the GUI needs to run?
Effectively, you are interrupting a queue, which can have lots of unforeseen consequences. Invoke is effectively the "polite" way of getting what you want to do into that queue, and this rule was enforced from .Net 2.0 onward via a thrown InvalidOperationException.
To understand what is actually going on behind the scenes, and what is meant by "GUI Thread", it's useful to understand what a Message Pump or Message Loop is.
This is actually already answered in the question "What is a Message Pump" and is recommended reading for understanding the actual mechanism that you are tying into when interacting with controls.
Other reading you may find useful includes:
What's up with Begin Invoke
One of the cardinal rules of Windows GUI programming is that only the
thread that created a control can access and/or modify its contents
(except for a few documented exceptions). Try doing it from any other
thread and you'll get unpredictable behavior ranging from deadlock, to
exceptions to a half updated UI. The right way then to update a
control from another thread is to post an appropriate message to the
application message queue. When the message pump gets around to
executing that message, the control will get updated, on the same
thread that created it (remember, the message pump runs on the main
thread).
and, for a more code heavy overview with a representative sample:
Invalid Cross-thread Operations
// the canonical form (C# consumer)
public delegate void ControlStringConsumer(Control control, string text); // defines a delegate type
public void SetText(Control control, string text) {
if (control.InvokeRequired) {
control.Invoke(new ControlStringConsumer(SetText), new object[]{control, text}); // invoking itself
} else {
control.Text=text; // the "functional part", executing only on the main thread
}
}
Once you have an appreciation for InvokeRequired, you may wish to consider using an extension method for wrapping these calls up. This is ably covered in the Stack Overflow question Cleaning Up Code Littered with Invoke Required.
There is also a further write up of what happened historically that may be of interest.
A control or window object in Windows Forms is just a wrapper around a Win32 window identified by a handle (sometimes called HWND). Most things you do with the control will eventually result in a Win32 API call that uses this handle. The handle is owned by the thread that created it (typically the main thread), and shouldn't be manipulated by another thread. If for some reason you need to do something with the control from another thread, you can use Invoke to ask the main thread to do it on your behalf.
For instance, if you want to change the text of a label from a worker thread, you can do something like this:
theLabel.Invoke(new Action(() => theLabel.Text = "hello world from worker thread!"));
If you want to modify a control it must be done in the thread in which the control was created. This Invoke method allows you to execute methods in the associated thread (the thread that owns the control's underlying window handle).
In below sample thread1 throws an exception because SetText1 is trying to modify textBox1.Text from another thread. But in thread2, Action in SetText2 is executed in the thread in which the TextBox was created
private void btn_Click(object sender, EvenetArgs e)
{
var thread1 = new Thread(SetText1);
var thread2 = new Thread(SetText2);
thread1.Start();
thread2.Start();
}
private void SetText1()
{
textBox1.Text = "Test";
}
private void SetText2()
{
textBox1.Invoke(new Action(() => textBox1.Text = "Test"));
}
Invoke((MethodInvoker)delegate{ textBox1.Text = "Test"; });
In practical terms it means that the delegate is guaranteed to be invoked on the main thread. This is important because in the case of windows controls if you don't update their properties on the main thread then you either don't see the change, or the control raises an exception.
The pattern is:
void OnEvent(object sender, EventArgs e)
{
if (this.InvokeRequired)
{
this.Invoke(() => this.OnEvent(sender, e);
return;
}
// do stuff (now you know you are on the main thread)
}
this.Invoke(delegate) make sure that you are calling the delegate the argument to this.Invoke() on main thread/created thread.
I can say a Thumb rule don't access your form controls except from main thread.
May be the following lines make sense for using Invoke()
private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.textBox1.Text = text;
}
}
There are situations though you create a Threadpool thread(i.e worker thread) it will run on main thread. It won't create a new thread coz main thread is available for processing further instructions. So First investigate whether the current running thread is main thread using this.InvokeRequired if returns true the current code is running on worker thread so call
this.Invoke(d, new object[] { text });
else directly update the UI control(Here you are guaranteed that you are running the code on main thread.)
It means that the delegate will run on the UI thread, even if you call that method from a background worker or thread-pool thread. UI elements have thread affinity - they only like talking directly to one thread: the UI thread. The UI thread is defined as the thread that created the control instance, and is therefore associated with the window handle. But all of that is an implementation detail.
The key point is: you would call this method from a worker thread so that you can access the UI (to change the value in a label, etc) - since you are not allowed to do that from any other thread than the UI thread.
Delegate are essentially inline Action's or Func<T>. You can declare a delegate outside the scope of a method which you are running or using a lambda expression(=>); because you run the delegate within a method, you run it on the thread which is being run for the current window/application which is the bit in bold.
Lambda example
int AddFiveToNumber(int number)
{
var d = (int i => i + 5);
d.Invoke(number);
}
It means that the delegate you pass is executed on the thread that created the Control object (which is the UI thread).
You need to call this method when your application is multi-threaded and you want do some UI operation from a thread other than the UI thread, because if you just try to call a method on a Control from a different thread you'll get a System.InvalidOperationException.
In an asynchronous OnMsgRecieved call, if I assign a value directly to a control it is not working.
Then i came to know that it was due to thread unsafe and i got following code to resolve the issue.
Now it is working. But i am not sure what it does practically. Can any one make me to understand it fully?
The code is:-
public void listener_OnMsgRecieved(string aResponse)
{
ShowResponseMessage(aResponse);
}
public void ShowResponseMessage(string aResponse)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.listBox.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(ShowResponseMessage);
this.Invoke(d, new object[] { aResponse });
}
else
{
this.listBox.Items.Add(aResponse);
label.Text = "Response received from Server :";
}
}
When ShowResponseMessage is called on a different thread from that of the UI, the InvokeRequired will return true, then you are using Control.Invoke to send a message to the Windows message queue.
The UI message pump which runs in the UI thread will pull the message and deliver it to the target control, the target control then sees that this is a message requesting that a delegate be invoked and the delegate is invoke by the control, this is now running on the UI thread and therefore the cross threading issue has been resolved.
The trick is that the delegate is not called directly on the non-UI calling thread. Using Windows messages the instruction to execute the delegate is passed to the UI thread which then executes the delegate in response to the message. 'Control.Invoke' uses the Windows [SendMessage][1], Control.BeginInvoke uses the [PostMessage][2] Win32 API to facilitate the message passing.
UI Controls cannot be update/changed from any thread other than the main thread/thread it was created on.
In your case the check InvokeRequired does the check to see if the thread that wishes to change the control is the creating thread, and if not passes the call back to the main thread/creator.
Have a look at How to: Make Thread-Safe Calls to Windows Forms Controls
If you use multithreading to improve the performance of your Windows
Forms applications, you must make sure that you make calls to your
controls in a thread-safe way.
Access to Windows Forms controls is not inherently thread safe. If you
have two or more threads manipulating the state of a control, it is
possible to force the control into an inconsistent state. Other
thread-related bugs are possible, such as race conditions and
deadlocks. It is important to make sure that access to your controls
is performed in a thread-safe way.
It is unsafe to call a control from a thread other than the one that created the control without using the Invoke method.
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 recently updated an application from VS2003 to VS2008 and I knew I would be dealing with a host of "Cross-thread operation not valid: Control 'myControl' accessed from a thread other than the thread it was created on" I am handling this in what I beleive is the correct way (see code sample below). I am running into numerous controls that are going to need a similar fix. Not wanting to have similar code for every label, textbox etc.. that are being accessed by a non UI thread. What are the ramifications of just setting the CheckForIllegalCrossThreadCalls = false for the entire app?
I found a CodeProject article with various workarounds and a warning at the bottom to NOT set the property. I am looking for other opinions/experiences on this issue.
private void ShowStatus(string szStatus)
{
try
{
if (this.statusBar1.InvokeRequired) { BeginInvoke(new MethodInvoker(delegate() { ShowStatus(szStatus); })); }
else { statusBar1.Panels[0].Text = szStatus; }
}
catch (Exception ex)
{
LogStatus.WriteErrorLog(ex, "Error", "frmMNI.ShowStatus()");
}
}
I found another article with some possible solutions SO Question 2367718
When you're not debugging, you'll still have problems.
From the documentation of Control.CheckForIllegalCrossThreadCalls:
Note that illegal cross-thread calls will always raise an exception when an application is started outside the debugger.
You'll need to correct the problems.
That being said, you mentioned:
Not wanting to have similar code for every label, textbox etc.. that are being accessed by a non UI thread.
I would reconsider this stance. You should try to move the logic running on a separate thread into separate methods or classes, which will in turn make marshaling the calls back into the UI much simpler. Over time, this will make your code much more reliable and maintainable.
Note that you can use Control.Invoke to marshal a whole set of calls to the UI in one call, too, instead of doing each single set operation individually. There really shouldn't be that many of them, when you finish.
Edit:
For example, it sounds like you're loading the data. Say you have (on your background thread), your data loading method:
var myData = LoadData();
this.Invoke( new Action( () =>
{
// Just set all of your data in one shot here...
this.textBox1.Text = myData.FirstName;
this.textBox2.Text = myData.LastName;
this.textBox3.Text = myData.NumberOfSales.ToString();
}));
The remarks section of the documentation for CheckForIllegalCrossThreadCalls makes it pretty clear that doing so is not a good idea
When a thread other than the creating
thread of a control tries to access
one of that control's methods or
properties, it often leads to
unpredictable results. A common
invalid thread activity is a call on
the wrong thread that accesses the
control's Handle property. Set
CheckForIllegalCrossThreadCalls to
true to find and diagnose this thread
activity more easily while debugging.
Note that illegal cross-thread calls
will always raise an exception when an
application is started outside the
debugger.