While maintaining some code, I discovered that we have an infinite hang-up in a background worker. The worker requires access to a script file. The original code was written to pop up a file dialog if no script file was defined, to allow the user to select one. It looks something like this:
private void bgworker_DoWork(object sender, DoWorkEventArgs e)
{
... snip ...
if (String.IsNullOrWhitespace(scriptFile))
{
scriptFile = PromptForScript();
}
... snip ...
}
private string PrompForScript()
{
string script = "";
OpenFileDialog openDialog = new OpenFileDialog();
if (openDialog.ShowDialog() == DialogResult.OK)
{
script = openDialog.FileName;
}
return script;
}
I've read up a bit about MethodInvoker, but almost all of the invoke methods require that you call them from a control. The background worker in question is running from a separate class, which doesn't extend Control. Do I use the form that calls the class with the bgworker for that? Or is there another way of interrupting the thread for user input?
It's not recommended to invoke the UI from the background worker DoWork event handler. BackgroundWorker is meant to do work on a non-UI thread to keep the UI responsive. You should ask for any file information before starting the BackgroundWorker object with RunWorkerAsync.
What you want to do is capture the SynchronizationContext on the UI thread and pass that along to the background worker. The BackgroundWorker can call Send() (synchronous, like Invoke) and Post() (asynchronous, like BeginInvoke) on the context to invoke back to the correct UI thread. That said, there is probably no need for the BackgroundWorker in this case- a regular threadpool thread would do just fine.
This (slightly modified) block of code from http://msmvps.com/blogs/manoj/archive/2005/11/03/74120.aspx should give you the general idea:
private void button1_Click(object sender, EventArgs e)
{
// Here we are on the UI thread, so SynchronizationContext.Current
// is going to be a WindowsFormsSynchronizationContext that Invokes properly
ctx = SynchronizationContext.Current;
ThreadPool.QueueUserWorkItem(
// This delegate is going to be invoked on a background thread
s => {
// This uses the context captured above to invoke
// back to the UI without the "messy" referencing
// of a particular form
ctx.Send(s2 =>
{
// Interact with your UI here- you are on the UI thread
},null);
}
);
}
If some Form kicks off a long-running process within another class that uses a BGworker, why wouldn't the form (or presenter, depending on UI architecture) handle the processing of the error state?
Perhaps, just pass back some status result (or throw a very targeted, specific exception that you can handle in the UI)?
Leave the background worker to determine if there IS an error, but leave handing the error (especially the UI portion of showing a message box) to the upper layers.
Sorry this didn't have more concrete code but it could go a lot of different ways depending on how your system is architected.
Well, the Form class has an Invoke method, so passing the form instance to the background working class should work.
Related
i am using the following function plot() to plot data on google maps.now when i am calling the same function from another button click event it is not getting executed rather going into else() statement.my plot function is as follows:
public void plot(double temp_lat, double temp_long, string temp_date, string temp_time, string temp_bty_value)
{
if (this.InvokeRequired)
{
// do something
}
else { this.Close(); }
}
i am calling this function from button click event as follows:
private void button6_Click_1(object sender, EventArgs e) /// refresh button
{
this.Invoke((MethodInvoker)(() =>
{
plot(28.5231445, 77.40388525, "17/06/20", "17:00:50", "82");
}));
}
when is the reason for this? i am new to invoking methods.please help
Edit:https://stackoverflow.com/a/43797637/6412780 The reason why i am using invocation because i was plotting 5 markers simultaneously on gmap from different threads.so for synchronization i am using invocation method.BUT now i want to update my data. i made a refresh button which contains new lat /long (passing manually here) to plot on the map.being on the same UI i called the plot() function directly ,but even then i wasn't able to execute the if statement. that is what i am doing .
In WinForms all1 UI operations – anything accessing any member of any control instance – need to be performed on the single thread executing UI operations.
Invoke can be used by a non-UI thread to cause the UI thread to execute code (with BeginInvoke this can be concurrently).
But an event handler for a control will always be running on the UI thread when triggered by the UI. So no need to switch threads. To run code on a different thread (eg. it would block the UI thread) there are various options, these days using async/await, to let the runtime work it out, is preferred.
In the question's code the event handler is already using Invoke which is pointless: it is already on the UI thread.
1 Simplifying here, the actual rules have subtleties for advanced use cases.
Invocation is required if you try to access elements, that are exclusive to one Threadfrom another Thread. It is very common when accessing GUI elements from a background thread. Here is an example:
Thread t = new Thread(() => plot(28.5231445, 77.40388525, "17/06/20", "17:00:50", "82"));
public void plot(double temp_lat, double temp_long, string temp_date, string temp_time, string temp_bty_value)
{
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)(() =>
{
this.Close();
}));
}
else {
this.Close();
}
}
thisseems to be a Form. If you call the Close method from another Thread you will most likely get an Exception (There are ways to prevent this, but thats not considered good style). You need to invoke that method (let the Form decide, when it is ready to execute the command)
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.
I am creating an automated test running application. In this part of the application, I am working on a polling server. It works by constantly polling the web server to determine when a new automated test should be run (for nightly automated runs of our GUI application).
When the polling server sees a request, it downloads all the information necessary and then executes the test run in a background worker. The problem is that part of the test run has OLE, COM, and other calls (for example, Clipboard.Clear()) that occur in the background worker thread. When one of these calls occurs, the following exception occurs:
Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it.
How can I mark a background worker thread as single thread apartment? The Main call in my Program.cs obviously already has that attribute.
This is not possible, BGW uses a threadpool thread. TP threads are always MTA, it cannot be changed. You will have to use a regular Thread, call SetApartmentState() before you start it. This thread also should pump a message loop, call Application.Run().
Maybe you ought to consider calling this code from the UI thread. Because in all likelihood, the COM server is running its methods on the UI thread anyway. Marshaling calls from a worker thread to the STA thread that created the COM server is automatic, COM takes care of it.
Or take the bull by the horns and marshal yourself. You can create your own STA thread to give the server a happy home. You'll find code in this post, be sure to create the COM object in your Initialize() override.
BackgroundWorker uses by default a ThreadPool thread, but you can override this behavior. First you need to define a custom SynchronizationContext:
public class MySynchronizationContext : SynchronizationContext
{
public override void Post(SendOrPostCallback d, object state)
{
Thread t = new Thread(d.Invoke);
t.SetApartmentState(ApartmentState.STA);
t.Start(state);
}
}
And override the default SynchronizationContext, like this, before you use your BackgroundWorker:
AsyncOperationManager.SynchronizationContext = new MySynchronizationContext();
NOTE: this can have performance effects on the rest of your application, so you might want to restrict the new Post implementation (for example using the state or d parameters).
I have not tested it, but if you invoke the WinForms Form, you should be back to the UI thread and most of the stuff should work again.
BackgroundWorker bgw = new BackgroundWorker();
bgw.DoWork += new DoWorkEventHandler(this.bgw_DoWork);
bgw.RunWorkerAsync();
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
// Invoke the UI thread
// "this" is referring to the Form1, or what ever your form is
this.Invoke((MethodInvoker)delegate
{
Clipboard.GetText();
// etc etc
});
}
You normally set it by defining attributre [STAThread()] on the entry point (e.g. Static Main).
I used +Conrad de Wet's idea and it worked great!
There is one small issue with that code though, you have to close the "this.Invoke....." like with a });
Here is Conrad de Wet's code with this fix:
BackgroundWorker bgw = new BackgroundWorker();
bgw.DoWork += new DoWorkEventHandler(this.bgw_DoWork);
bgw.RunWorkerAsync();>
private void bgw_DoWork(object sender, DoWorkEventArgs e)
{
// Invoke the UI thread
// "this" is referring to the Form1, or what ever your form is
this.Invoke((MethodInvoker)delegate
{
Clipboard.GetText();
// etc etc
});
}
I've inherited code where BeginInvoke is called from the main thread (not a background thread, which is usually the pattern). I am trying to understand what it actually does in this scenario.
Does the method being called in the BeginInvoke get in line of messages that come down to the window? The docs say asynchronously, so that is my assumption.
How does the framework prioritize when to kick off the method called by BeginInvoke?
Edit: The code looks like this:
System.Action<bool> finalizeUI = delegate(bool open)
{
try
{
// do somewhat time consuming stuff
}
finally
{
Cursor.Current = Cursors.Default;
}
};
Cursor.Current = Cursors.WaitCursor;
BeginInvoke(finalizeUI, true);
This is happening in the Form_Load event.
edit
Now that we see the code, it's clear that this is just a way to move some initialization out of Form_Load but still have it happen before the user can interact with the form.
The call to BeginInvoke is inside Form_load, and is not called on another object, so this is a call to Form.BeginInvoke. So what's happening is this.
Form_Load passes a delegate to Form.BeginInvoke, this puts a message in the form's message queue that is ahead of all user input messages. It sets the cursor to a wait cursor.
Form_Load returns, and the rest of form initialization is allowed to complete, the form most likely becomes visible at this point.
Once the code falls into the message pump, the first thing is sees in the queue is the delegate, so it runs that.
as the delegate completes, it changes the cursor back to the normal cursor, and returns
profit!
original post below
I depends on the object that you call BeginInvoke on. If the object is derived from Control then Control.BeginInvoke will run on the thread that created the control. See JaredPar's answer.
But there is another pattern for the use of BeginInvoke. if the object is a delegate, then BeginInvoke runs the callback on a separate thread, one that may be created specifically for that purpose.
public class Foo
{
...
public Object Bar(object arg)
{
// this function will run on a separate thread.
}
}
...
// this delegate is used to Invoke Bar on Foo in separate thread, this must
// take the same arguments and return the same value as the Bar method of Foo
public delegate object FooBarCaller (object arg);
...
// call this on the main thread to invoke Foo.Bar on a background thread
//
public IAsyncResult BeginFooBar(AsyncCallback callback, object arg)
{
Foo foo = new Foo();
FooBarCaller caller = new FooBarCaller (foo.Bar);
return caller.BeginInvoke (arg);
}
This pattern is one reason that BeginInvoke is called from the main thread rather than from a background thread.
In the case BeginInvoke is called on a UI thread it will still go through the process of posting a Windows Message to the message queue where the message will wait to be processed. The delegate will run when the message is processed. This message is not prioritized in any way that's different than it being called from the background thread.
In this scenario I suspect the call looks like:
private void Button1_Click(object sender, ButtonClickEventArgs e)
{
Control.BeginInvoke(new MethodInvoker(()=> /* code etc. */));
}
What's happening is that some code will run on on a threadpool thread, and update the control on the thread that created the control whereas if Control.Invoke was used, some code would run on the thread that created the control, and update the control on that thread as well.
Prior to widespread BackgroundWorker use, you had to synchronize back to the UI thread before doing any operations on Controls created on the UI thread (i.e. pretty much every Control).
There's a pretty good reference example here down in the "Thread-Safe Calls to a Windows Forms Control" section.
Scenario
Lets say you have a C# WinForms application that doing some data processing.
You have a method that retrieves data from a database that is called by the UI thread.
The background thread then runs off to do this task.
You want the UI to carry on doing its thing and not be locked up and unresponsive.
QUESTION
How do you let the background thread run off and do its processing and then automatically alert the UI thread when it has returned the results?
If you don't use a background worker thread (for whatever reason) then you must fire an event from your thread which is handled by the UI thread. For example I have this code that scans my mp3s and fires and event for each album found and then another event when it finished (or is stopped):
public void Build()
{
FindAlbums(Root);
// Final update
if (Library_Finished != null)
{
Library_Finished(this, null);
}
}
private void FindAlbums(string root)
{
// Find all the albums
string[] folders = Directory.GetDirectories(root);
foreach (string folder in folders)
{
string[] files = Directory.GetFiles(folder, "*.mp3");
if (files.Length > 0)
{
// Add to library - use first file as being representative of the whole album
var info = new AlbumInfo(files[0]);
if (Library_AlbumAdded != null)
{
Library_AlbumAdded(this, new AlbumInfoEventArgs(info));
}
}
FindAlbums(folder);
}
}
Then in the UI thread (this is WinForms code):
private void Library_AlbumAdded(object sender, AlbumInfoEventArgs e)
{
if (dataGridView.InvokeRequired)
{
dataGridView.Invoke((MethodInvoker)delegate { AddToGrid(e.AlbumInfo); });
}
else
{
AddToGrid(e.AlbumInfo);
}
}
private void Library_Finished(object sender, EventArgs e)
{
if (dataGridView.InvokeRequired)
{
dataGridView.Invoke((MethodInvoker)delegate { FinalUpdate(); });
}
else
{
FinalUpdate();
}
}
I would, however, recommend that you investigate the background worker thread, as it does so much of the housekeeping for you. However, the same handling code would be needed in the RunWorkerCompleted event to update the UI.
There are several ways of doing this, but the easiest way is to use a BackgroundWorker.
Essentially it has two delegates, the DoWork and the WorkCompleted. DoWork executes on a seperate thread and the WorkCompleted callback happens on the UI thread.
Here's more info:
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
You can use the BackgroundWorker to do your time-intensive processing in its DoWork event handler. Then handle the RunWorkerComplete event -- it will fire when the DoWork method is finished. While all this is going on, your UI thread will be happily running along.
If you're using .NET 2.0 or newer, then this is made much easier with the BackgroundWorker thread. It has its own RunWorkerCompleted event that does just what you need.
I would highly recommend the BackgroundWorker in fact. It has the functionality most developers are after when creating threads. They're also easier to cancel gracefully, and they even have the ability to report progress.
Try to use BackgrounWorker and register a handler to the its RunWorkerCompleted event.
In Winforms you can use the .Invoke method (and check the .InvokeRequired property) to marshall a call back to the UI thread. You don't so much notify the UI thread - it keeps going on and doesn't wait for any sort of a completion, but you can interact with a control (for example, update the text property of a label) from another thread using the Invoke method.
You can also use the BackgroundWorker object (read MSDN to find out more about it), which implements a callback functionality to run some code on the UI thread after the background work is completed.
If you are talking about a WinForm app, you can make changes to any UI objects using the Invoke method on your form (or any of the controls on the form). You can also find useful the InvokeRequired property
You can store a reference to the UI thread Dispatcher by using Dispatcher.CurrentDispatcher (obviously in a method called by GUI thread). Using this object you can use the BeginInvoke or Invoke methods in your working thread to execute a method on the GUI thread notifying it that you have completed work. Personally I find this method to be slightly more flexible than using a background worker object and can produce slightly more readable code.
There's an easy way of working with multiple threads in C#. It is called BackgroundWorker.
You should check it out: BackgroundWorker Tutorial
As was mentioned many times, the BackgroundWorker class can be used.
Alternatively, you could do something akin to the following:
void buttonGo_Clicked( object sender, EventArgs e )
{
MyAsyncClass class = new MyAsyncClass();
class.LongOperationFinished += (LongOperationFinishedEventHandler)finished;
class.BeginLongOperation();
}
void finished( object sender, EventArgs e )
{
if( this.InvokeRequired ) {
this.BeginInvoke( (LongOperationFinishedEventHandler)finished, sender, e );
return;
}
// You can safely modify the gui here.
}