Control.Invoke() stucks - c#

I know there are several threads concerning this topic, but I think mine is different.
In my application I open a form where the user can input some parameters for a upcomming printing. This printing is supposed to be run in a background worker. So I fire that background worker with the event "OnFormClosing".
Within that background worker I need to access the GUI and change/read it, so I need a control.Invoke(). "Sometimes" the Invoke keeps stuck at the invoke call itself and doesn't execute the delegate. My main thread is working fine and is not blocked. I still can interact with the GUI doing other stuff. Before posting any code: Are there any other conditions for executing a control.Invoke() other than
The main GUI thread is not blocked
The contorl must exist, the handle created and not be disposed
The main thread doesn't need to be free and exactly the invoke is called correct? It should continue once the main thread is idle...
Thanks for any help
Update:
Here is the thread situation during that issue:
The Main thread is executing this:
Application.Run(appContext);
So it is idle.
The worker thread is waiting at this line:
fileName = (string)cbPrintFile.Invoke(new Func<String>(() => cbPrintFile.Text));
which is not executed like I state above. cbPrintFile is a combobox

Invoke is "enqueue and wait for it to be processed". If it is becoming "stuck", that suggests that you have deadlocked, for example because the UI thread is still in an event-handler waiting on the worker. If the code is properly de-coupled, you can probably replace the Invoke with BeginInvoke, which allows the worker to continue after queuing the work. Of course, it would also be good to ensure that the UI is never waiting on a worker. This can be done accidentally if trying to hold a lock (on the same object) in both places. You can investigate simply by pausing the application, pressing ctrl+d,t to bring up the threads, and ctrl+d,c to see the call-stack of each in turn.

Related

System.Threading.Thread - perform operation on it

Ok so lets say all I have is the reference of a System.Threading.Thread called thread A and I'm on another thread, lets say thread B. Now I need to execute a bit of code on thread A for a moment, then switch back. Using the reference I have, how can I Invoke thread A to do an action in it?
Well I'm making a c++/cli library. One of my objects has a thread affinity. I enter a method, I need to swap threads like you would in a Dispatcher.Invoke.
void AllegroSharp::Display::DrawToBackBuffer(BitmapImage^ image)
{
al_draw_bitmap(image->GetBitmap(), (float)image->Rect->Position->X, (float)image->Rect->Position->Y, 0);
}
DrawToBackBuffer gets called on thread B and al_draw_bitmap needs to be called on Thread A, which I have a reference to. How can I do this on thread A? Thread B is just some thread that c# spawned when I did a Task.Run in managed code.
Threads run one set of instructions from start to finish. If thread A is already running, it will execute whatever code it's been told to run from start to finish. You won't be able to change what it's running unless it is actively monitoring some shared memory for instructions on what to do next. Typically the way you implement this is by having a thread run in a loop and, inside that loop, check a message queue. Then have other threads add messages to that queue to give the looping thread work to do. There are a lot more details to make it work right, but that's the basic idea.
If, in your particular scenario, thread A is the application's GUI thread, this message passing mechanism is already set up for you, and you can use Control.Invoke (winforms) or Dispatcher.Invoke (WPF) to pass a unit of work to the GUI thread and wait for it to be completed.
Edit: this answer has been rendered less applicable by the addition of new information to the question. Ah well.

My processing thread is going too fast for my UI thread

I have a C# program that is checking for the existence of files and registry keys and using AppendText() on a Form.Textbox for every file and registry key it is looking for.
This is running in an asynchronous BackgroundWorker and now my background worker is actually processing so quickly that my UI thread gets clogged up with AppendText commands and the program crashes. How can I synchronize the BackgroundWorker and UI thread so that the BackgroundWorker doesn't start processing again until the UI thread is ready?
You have a BackgroundWorker, so you have everything you need. The progress event is called on the UI thread, so if the worker reports progress in the standard way (by calling ReportProgress(int32, object), and passing the string to be appended as the second parameter, the form's progress handler can call AppendText. The background thread will never outrun the UI that way.
I suspect you're calling BeginInvoke to update your UI. Another way to solve the problem would be to call Invoke.
You can do much better if you have your background worker save up, say, 10 lines, and then pass them all to the progress event at once. That'll reduce the overhead of updates and cause your background thread to process faster.
One way that comes to mind is queuing the commands and allowing the UI thread to handle them at its own speed :: IE create a generic list (let's call it appendtext) of the arguments, the background worker adds to the list and the UI thread reads, calls, then deletes from the list

Cross Thread Exception When Closing Application

I am sometimes getting a cross thread exception when closing my application which uses two threads (main thread and secondary). I think what is happening is that the main UI thread is being disposed while the secondary one is still running, and since the secondary one sometimes invokes things on the UI thread it is crashing.
Do I need to manually close the secondary thread in the FormClosing event?
Thanks for the info.
Do I need to manually close the secondary thread?
No and yes.
No, if your secondary thread is a background thread. You can inspect/set the IsBackground property on your secondary thread. All background threads are are automatically stopped by CLR when there is no foreground thread running anymore. All ThreadPool threads, for example, are background threads.
Yes, however, is when you perform some critical task in your secondary thread and you don't want it to be abruptly stopped. In that case, you will have to implement appropriate logic to stop your secondary thread.
Once you have a long-running dedicated thread, you have to implement shutdown logic for it. Reason is simple: the app is not killed by OS until at least one thread alive. And yes, there is no such thing as "main thread", all threads are equal from OS perspective.
Given that, once your app plans to exit, you must
Signal to the second thread that termination expected
Wait for the second thread until it exits from his thread proc
Now you're free to exit.
The recommended approach in multi-threaded windows application is using Method Invocation instead of directly manipulating controls which were created on another thread. This way you never get Cross Thread Exception. For example you can set a textbox's text like this:
form1.BeginInvoke(new MethodInvoker(()=>textbox1.text = "Hello!"));
For more information see:
http://msdn.microsoft.com/en-us/library/ms171728(v=vs.85).aspx

C# network application threading causes program to block

I am working on a network application with threading. I have an event handler which results in a form showing on the screen. The problem is that the thread that makes this call blocks right after, so the form that shows blocks as well.
I have hacked this problem by making that function change something in the form it's currently in, and then used invoke required to force the new form onto that thread. This is a terrible hack, what is the right way to make the new form.Show() method go through its own thread.
Note that I have tried just making a worker thread that runs only form.show() but the form disappears right after the call.
Thank you,
PM
You don't want UI elements being created in their own threads. The primary thread that launched your application should be the UI thread. Create and show all elements on this thread. All your heavy, long-time or blocking work should be done on their own threads.
You can use BackgroundWorker to execute a single additional task without blocking your UI and get automatic synchronization when you need to make updates to the main (UI) thread such as to update progress bars or show a final result.
If you need multiple threads doing long-running work, use the ThreadPool. You will have to do your own cross-thread synchronization if you need to update UI elements. There are a ton of answers on how to do that already if that's the route you go.
If you have multiple threads that are being blocked while waiting for something to happen, you should use threads yourself. This will keep the ThreadPool from being starved of threads because they are all blocking. (I believe this has been changed in .NET 4 so if you're targeting that version you can probably easily continue using the ThreadPool in this situation.)
Have you tried placing the blocking call in a BackgroundWorker (separate thread)? When that blocking call is done, your background-worker thread completes (which is handled by your main UI thread). Then in that completed handler you can show your form/message or whatever...
If you haven't tried that then give it a shot. Note that i have not tested this since i dont know exactly what you're doing.
Cheers.

How do I Yield to the UI thread to update the UI while doing batch processing in a WinForm app?

I have a WinForms app written in C# with .NET 3.5. It runs a lengthy batch process. I want the app to update status of what the batch process is doing. What is the best way to update the UI?
The BackgroundWorker sounds like the object you want.
The quick and dirty way is using Application.DoEvents() But this can cause problems with the order events are handled. So it's not recommended
The problem is probably not that you have to yield to the ui thread but that you do the processing on the ui thread blocking it from handling messages. You can use the backgroundworker component to do the batch processing on a different thread without blocking the UI thread.
Run the lengthy process on a background thread. The background worker class is an easy way of doing this - it provides simple support for sending progress updates and completion events for which the event handlers are called on the correct thread for you. This keeps the code clean and concise.
To display the updates, progress bars or status bar text are two of the most common approaches.
The key thing to remember is if you are doing things on a background thread, you must switch to the UI thread in order to update windows controls etc.
To beef out what people are saying about DoEvents, here's a description of what can happen.
Say you have some form with data on it and your long running event is saving it to the database or generating a report based on it. You start saving or generating the report, and then periodically you call DoEvents so that the screen keeps painting.
Unfortunately the screen isn't just painting, it will also react to user actions. This is because DoEvents stops what you're doing now to process all the windows messages waiting to be processed by your Winforms app. These messages include requests to redraw, as well as any user typing, clicking, etc.
So for example, while you're saving the data, the user can do things like making the app show a modal dialog box that's completely unrelated to the long running task (eg Help->About). Now you're reacting to new user actions inside the already running long running task. DoEvents will return when all the events that were waiting when you called it are finished, and then your long running task will continue.
What if the user doesn't close the modal dialog? Your long running task waits forever until this dialog is closed. If you're committing to a database and holding a transaction, now you're holding a transaction open while the user is having a coffee. Either your transaction times out and you lose your persistence work, or the transaction doesn't time out and you potentially deadlock other users of the DB.
What's happening here is that Application.DoEvents makes your code reentrant. See the wikipedia definition here. Note some points from the top of the article, that for code to be reentrant, it:
Must hold no static (or global) non-constant data.
Must work only on the data provided to it by the caller.
Must not rely on locks to singleton resources.
Must not call non-reentrant computer programs or routines.
It's very unlikely that long running code in a WinForms app is working only on data passed to the method by the caller, doesn't hold static data, holds no locks, and calls only other reentrant methods.
As many people here are saying, DoEvents can lead to some very weird scenarios in code. The bugs it can lead to can be very hard to diagnose, and your user is not likely to tell you "Oh, this might have happened because I clicked this unrelated button while I was waiting for it to save".
Use Backgroundworker, and if you are also trying to update the GUI thread by handling the ProgressChanged event(like, for a ProgressBar), be sure to also set WorkerReportsProgress=true, or the thread that is reporting progress will die the first time it tries to call ReportProgress...
an exception is thrown, but you might not see it unless you have 'when thrown' enabled, and the output will just show that the thread exited.
Use the backgroundworker component to run your batch processing in a seperate thread, this will then not impact on the UI thread.
I want to restate what my previous commenters noted: please avoid DoEvents() whenever possible, as this is almost always a form of "hack" and causes maintenance nightmares.
If you go the BackgroundWorker road (which I suggest), you'll have to deal with cross-threading calls to the UI if you want to call any methods or properties of Controls, as these are thread-affine and must be called only from the thread they were created on. Use Control.Invoke() and/or Control.BeginInvoke() as appropriate.
If you are running in a background/worker thread, you can call Control.Invoke on one of your UI controls to run a delegate in the UI thread.
Control.Invoke is synchronous (Waits until the delegate returns). If you don't want to wait you use .BeginInvoke() to only queue the command.
The returnvalue of .BeginInvoke() allows you to check if the method completed or to wait until it completed.
Application.DoEvents() or possibly run the batch on a separate thread?
DoEvents() was what I was looking for but I've also voted up the backgroundworker answers because that looks like a good solution that I will investigate some more.

Categories

Resources