C# Threading and Forms: NotSupportedException - Use Control.Invoke? - c#

I am trying to run an application with at least two threads: One form for the user interface and one or more worker threads. They are jointly reading/writing from a static class through a number of other classes.
This is why I am passing an instance of the worker class to the display form. I guess that is why it goes wrong for me:
public class CoCoon
{
private Screen displayForm;
private Worker worker;
public ThreadedApp()
{
worker = new Worker (1024);
displayForm = new Screen(worker);
}
public void Run()
{
//thread 1: display form
Thread screenThread = new Thread(() => Application.Run(displayForm));
//thread 2: background worker
Thread workerThread = new Thread(worker.Run) {IsBackground = true};
screenThread.Start();
Thread.Sleep(1000); //if I don't wait a while, I get an ObjectDisposedException!
workerThread.Start();
}
The threads and objects are initiated just fine, but as soon after the Form_Load method is has been handled, an error is thrown on the Application.Run(displayForm) line above. It is an NotSupportedException, with a remark that I should use Control.Invoke. But I am not sure I understand, because I am not letting threads other than the display form's use the controls on it.
I am new to threading. Can anyone help me on my way? Thanks!
PS: One detail - I am developing this for the Windows Mobile platform.
EDIT After popular request hereby the Stack Trace
at Microsoft.AGL.Common.MISC.HandleAr(PAL_ERROR ar)\r\n at
System.Windows.Forms.Control.get_Visible()\r\n at
System.Windows.Forms.Form._SetVisibleNotify(Boolean fVis)\r\n at
System.Windows.Forms.Control.set_Visible(Boolean value)\r\n at
System.Windows.Forms.Application.Run(Form fm)\r\n at
CoCoonWM6.CoCoon.<Run>b__1()\r\n

I recommend that you only have one UI thread, the main thread. You can use your other threads for background operations, but keep all UI stuff on the main thread.
The UI thread should be the only one calling Application.Run. WinForms has other requirements for the UI thread (such as being STA), and those are satisfied by the main thread. In theory, it may be possible for WinForms to support two UI threads, but it's certainly not easy.
I normally recommend other forms of synchronization when you need to update UI controls from a background thread - TaskScheduler or SynchronizationContext. On the mobile platform, unfortunately, your only option is Control.Invoke.

Check out the stack trace for the exception (and post it). You are almost certainly accessing some Control from the worker thread.
This is how you can modify access to a Control (in this example a Label) after you find where you are accessing controls from non-UI threads:
if (label13.InvokeRequired)
{
ChangeTextDelegate changeText = new ChangeTextDelegate(anyChangeTextMethod);
label13.Invoke(changeText, new object[] { newText });
}
else
{
label13.Text = newText;
}

Looks like you're trying to use GUI elements in the background thread. That would explain why you have to call Sleep (otherwise the form and its controls don't finish loading before you try to use them) as well as the Control.Invoke exception (you can't use GUI elements from a non-UI thread). See the docs for Control.Invoke for how you should use it.
Since you don't have BackgroundWorker and Px in the CF, you're indeed forced to use threads directly - though the ThreadPool would probably be better than instantiating new threads, most of the time.

Related

WPF multi-thread progress update

I'm need to display some form of feedback to the user, while a small process (7-10 seconds) takes place in the background.
I had no issues in the past using separate threads and BackgroundWorkers in Windows Forms, but its proving difficult in WPF.
I have read many articles, in this respect, and how I should be using dispatchers in WPF to start a new thread, etc. However, when I try to use a BackgroundWorker to display a form of waiting image feedback, it simply remains static.
I don't believe that it matters, but it uses mui from FirstFloor (https://github.com/firstfloorsoftware/mui).
I'm trying to use the built-in ProgressRing feature (which works no problems when run within the same thread and there are no other major tasks running in the background.
Adding a BackgroundWorker, brings an exception due to cross thread access of objects, even though many blogs states that BackgroundWorks in WPF are cross thread aware and safe to run.
The following is the closest code that generates what I need.
private async void MyTaskProcess()
{
await Dispatcher.BeginInvoke(DispatcherPriority.Send, new ThreadStart(() =>
{
try
{
//Update the waiting ring image
ProgressRing.IsActive = true;
}
catch
{
ProgressRing.IsActive = false;
MessageBox.Show("Exception Thrown");
}
}));
await Dispatcher.BeginInvoke(DispatcherPriority.Background, new ThreadStart(() =>
{
try
{
//Run the main MS Excel export function
Export2Excel();
ProgressRing.IsActive = false;
}
catch
{
MessageBox.Show("Exception Thrown");
}
}));
}
Any feedback is appreciated.
The way you do this in a modern WPF application is to start a new Task in which you do the work; under the covers this will perform the work on a thread pool thread:
Task.Factory.StartNew(this.DoWork)
Now in DoWorkto report progress you InvokeAsync back to the main thread whenever the porgress count changes:
void DoWork()
{
foreach(var item in this.WorkItems)
{
// Do something
// Report Progress
++progress
Application.Current.Dispatcher.InvokeAsync(() => this.Progress = progress);
}
}
Adding a BackgroundWorker, brings an exception due to cross thread access of objects, even though many blogs states that BackgroundWorks in WPF are cross thread aware and safe to run.
BackgroundWorker works fine with WPF, as long as you create and start the BGW on the UI thread. (As a side note, BGW has the same restriction on Windows Forms). As other commenters have noted, the proper way to do progress updates with BGW is using ReportProgress, not Dispatcher.
However, I'd recommend using the newer Task.Run with IProgress<T> for progress updates. I have a blog post that compares/contrasts the old BGW progress updates with the new IProgress<T>-based progress updates.
It's difficult to say what your code should look like, since the code you posted doesn't actually run anything on a background thread. In particular, if Export2Excel must be run on the UI thread, and that's all your work is doing, then there's no point in using BGW or Task.Run at all, since nothing can run on the background thread anyway.
you go, to the below link written by me and read carefully.I hope you will definetily solve your problem:
Threads in WPF

STA call from MTA

I am just starting to deal with STA/MTA issues, so apologies for the simplicity of the question. I couldn't find an answer I could actually understand at the bottom of the ladder here.
I am writing a plugin for another piece of software, and come to a point in a worker thread that I need to create some UI elements. I understand that I cannot do that from inside the worker thread since it is not an STA thread, and that I need to get back to the Main (or just another?) STA thread to create the UI elements. Some clarifications would help greatly.
Do all STA threads have the same 'rights', i.e. if the main thread is STA and creates a Window, adds some UI elements to it. Then spawns off another STA thread, and that second thread likewise creates some UI elements, are they doing it in the same 'space' (poor word choice, but I don't know what else to use) and can access each other's UI elements without causing death and destruction? Or do I need to explicitly jump back to the Main/Original STA thread and ONLY ever create UI elements from THAT (not just ANY) STA thread?
If that is the case (only 1 STA thread is allowed to make UI elements) how do I do that correctly? I have seen many posts that related to this but for some reason I can't quite catch what's going on, and would love a REAL simple answer.
Please no 'Here's a cool slick way of doing...' I just need the simple way of at the point of execution where I need some UI elements jumping back over to the main STA thread if that's what's necessary.
If it is not necessary, then I will just make that worker thread an STA thread and continue on my way, is that fair? Or am I courting disaster?
if the main thread is STA and creates a Window, adds some UI elements to it. Then spawns off another STA thread, and that second thread likewise creates some UI elements, are they doing it in the same 'space' [snip...] and can access each other's UI elements without causing death and destruction?
If Thread A and B are both STA, then they can each create and update their own UI elements, but not eachothers. Any other threads that want to affect the UI have to use one of the BeginInvoke style methods to ask the appropriate thread to do the update.
If it is not necessary, then I will just make that worker thread an STA thread and continue on my way, is that fair? Or am I courting disaster?
You may not be able to make the worker thread an STA thread if it's been set to MTA and initialized. You may have to make a new thread.
How do you do it? It seems like you want to use WPF (System.Windows.*) for your UI - so If the app that you are "plugging into" is also using WPF, you should be able to access it and re use it's UI thread. If not, you can make a new thread, and create a new Application on it and call Run. This should set up a dispatcher for you.
Something like this (pseudo code sort-of copied from some working code I have elsewhere)
Dispatcher dispatcher = null; // we 'get to' the UI thread via the dispatcher
if(Application.Current) { // re use an existing application's UI thread
dispatcher = Application.Current.Dispatcher;
} else {
var threadReadyEvent = new ManualResetEvent(false);
var uiThread = new Thread(() => {
Thread.CurrentThread.SetApartmentState(ApartmentState.STA);
var application = new Application();
application.Startup += (sender, args) => {
dispatcher = application.Dispatcher;
threadReadyEvent.Set();
};
// apps have to have a "main window" - but we don't want one, so make a stub
var stubWindow = new Window {
Width = 1, Height = 1,
ShowInTaskbar = false, AllowsTransparency = true,
Background = Brushes.Transparent, WindowStyle = WindowStyle.None
};
application.Run(stubWindow);
}){ IsBackground = true };
uiThread.Start();
threadReadyEvent.WaitOne();
threadReadyEvent.Dispose();
}
dispatcher.Invoke(() => {
// ask the UI thread to do something and block until it finishes
});
dispatcher.BeginInvoke(() => {
// ask the UI thread to do something asynchronously
});
and so forth
If a thread creates a control. Only this specific thread can interact with it, even if there are other STA threads.
In WinForms you would invoke a method on the control: Control.Invoke.In WPF you have the dispatcher to do it: Dispatcher.Invoke.
WinForms:
form1.Invoke(/* a delegate for your operation */)
WPF:
window1.Dispatcher.Invoke(/* a delegate for your operation */)
What you do is instead of changing an object in a "single apartment" you ask (invoke) the STA thread in control of it to do it (the delegate you invoke) for you. You also have BeginInvoke for doing it asynchronously.

Invoke(Delegate)

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.

Dispatcher to Thread relationships in WPF

It is not entirely clear to me how many Dispatchers there are in an application and how they are related to, or referenced from Threads.
As I understand it, a WPF application has 2 threads (one for input, the other for UI) and 1 dispatcher (associated to the UI-Thread). What if I create another thread - let's call it "worker thread" - when I call Dispatcher.CurrentDispatcher on the worker thread, which dispatcher will i get?
Another case:
Assume a console application with 2 threads - the main thread, and an input-thread. On the main thread, I first create the input-thread and then i call Application.Run()
Thread thread = new Thread(new ThreadStart(UserInputThreadFunction));
thread.Start();
Application.Run();
There will be one dispatcher, right? On the input-thread, does Dispatcher.CurrentDispatcher return the dispatcher of the main thread? Or what is the proper way of getting an instance to the main thread's dispatcher?
Could it be, that there are more than one dispatcher in a WPF application? Is there any case, it would make sense to create another dispatcher?
WPF application has 2 threads (one
for input, the other for UI)
This statement is not entirely correct. A WPF application has only one UI thread that handles all the UI interaction and user input. There is also a "hidden" thread responsible for rendering, but normally developers don't deal with it.
Dispatcher / Thread relationship is one to one, i.e. one Dispatcher is always assoticated with one thread and can be used to dispatch execution to that thread. Dispatcher.CurrentDispatcher returns the dispatcher for the current thread, that is, when you call Dispatcher.CurrentDispatcher on a worker thread you get a dispatcher for that working thread.
Dispatchers are created on demand, which means if you access Dispatcher.CurrentDispatcher and there is no dispatcher associated with the current thread, one will be created.
That being said, the number of dispatchers in the application is always less or equal to the number of threads in the application.
WPF application by default has only one Dispatcher. The dispatcher is the only thread that will allow you to interact with UI elements. It abstracts implementations from you, so you only need to worry about being on the UI thread ie the Dispatcher.
If you are trying to directly interact with a visual (eg, set a text on a text box using txtBkx.Text = "new"), from a worker thread, then you will have to switch to a UI thread:
Application.Current.Dispatcher.Invoke(
() => { txtBkx.Text = "new"; });
Alternatively you can use SynchronizationContext.Current (while on a UI thread) and use that to execute delegates on a UI thread from a different thread. As you should note that Dispatcher.CurrentDispatcher may not always be set.
Now you can in fact create different WPF windows in the same application and have an individual dispatcher for each window:
Thread thread = new Thread(() =>
{
Window1 w = new Window1();
w.Show();
w.Closed += (sender2, e2) =>
w.Dispatcher.InvokeShutdown();
System.Windows.Threading.Dispatcher.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
As a side note remember in MVVM, you can update model from a non UI thread and raise property changed events from a non UI thread, as WPF will marshal PropertyChanged events for you. Raising CollectionChanged has to be on a UI thread though.
A dispatcher is always associated with a thread and a thread can have at most one dispatcher running at the same time. A thread does not need to have a dispatcher.
By default there is only one Dispatcher - For the UI. Sometimes it makes sense to have other dispatchers, other time it does not. A dispatching thread needs to block in the Dispatcher.Run() method in order to process invokes to the dispatcher. A thread such as your console input thread will not be availible to process invokes.

How to check a thread is done, then fill progress bar in C# / WPF

I am just working on my first GUI application on Windows.
I have a WPF GUI to a small C# utility which copies files. When the button is clicked to copy, I obviously don't want the GUI to hang. So, I fire off a new thread to run the method which copies the files. I assume I'm on track so far and there's no "better" way of doing it in C#?
Now, I have a ProgressBar which I want to appear filled when the thread is done. (It's fine running as indeterminate for now). How do I check when the copying is done?
So, so far I have:
Thread t = new Thread(delegate()
{
po.Organise(inputPath, outputPath, recursive);
});
t.Start();
PBar.IsIndeterminate = true;
And I want something after that that works like:
if (t.Done)
{
PBar.Value = 100;
}
Have a look at the BackgroundWorker class. It supports events like RunWorkerCompleted or ProgressChanged.
Have a look here, too (this is about threading in general + backgroundworker, again).
As already stated, consider the use of the BackgroundWorker class. It was designed for these situations and exposes events suited for what you are trying to accomplish.
Use the ProgressChangedevent to report progress incrementally and the RunWorkerCompleted for when the task finishes. Check the MSDN page for code samples.
Wrap the if (t.Done) block in its own method. Invoke this method from the end of your worker thread.
Also, you might want to give the worker thread a name to make it easier to spot in the debugger.
You need a callback method. This should get you started. It uses an AsyncCallback, which is the best way to tackle this type of issue.
I just looked up an example I've been using for a project and stripped out the code specific to my app:
System.Windows.Forms.MethodInvoker mi = new System.Windows.Forms.MethodInvoker(delegate()
{
// Do your file copy here
});
AsyncCallback ascb = new AsyncCallback(delegate(IAsyncResult ar)
{
this.Dispatcher.Invoke(new ThreadStart(delegate (){
// set progressbar value to 100 here
}), null);
});
mi.BeginInvoke(ascb, null);
The quick and easy hack would be to just update the UI at the end of your anonymous method in your thread. Obviously you can't update it directly, but you can use Dispatcher.Invoke:
Thread t = new Thread(delegate()
{
po.Organise(inputPath, outputPath, recursive);
Dispatcher.Invoke(new Action(()=>{PBar.Value = 100;}),null);
});
t.Start();
As a general Windows programming principal, you have to make calls to update the UI from the UI thread (the one that is processing messages through a message pump).
In Windows Forms, the way that this was done was through the implementation of the ISynchronizeInvoke interface on the Control class, primarily through the implementation of the Invoke method.
With the release of .NET 2.0, it was realized that a better mechanism was needed to marshal calls into the correct context. That's where the SynchronizationContext comes in.
This class abstracts the interface you would use for marshaling calls to different contexts, allowing for specific implementations depending on the context.
So whether or not Windows Forms is the environment, or WPF, one call can be made in the same way across those contexts with the same effect (marshaling the call).
In your particular case, because you are using a closure (anonymous method), you can take advantage of the fact that a SynchronizationContext is available to you (through the static Current property) at the invocation site of the Thread to provide the mechanism to call back to the UI thread from your background thread:
// Get the synchronization context.
// This is in the UI thread.
SynchronizationContext sc = SynchronizationContext.Current;
// Create the thread, but use the SynchronizationContext
// in the closure to marshal the call back.
Thread t = new Thread(delegate()
{
// Do your work.
po.Organise(inputPath, outputPath, recursive);
// Call back using the SynchronizationContext.
// Can call the Post method if you don't care
// about waiting for the result.
sc.Send(delegate()
{
// Fill the progress bar.
PBar.Value = 100;
});
});
// Make the progress bar indeterminate.
PBar.IsIndeterminate = true;
// Start the thread.
t.Start();
Note, if you don't care about waiting for the result of the call back to the UI thread, you can make a call to the Post method instead, which will dispatch the call to the UI thread without waiting for that call to complete.

Categories