There is a sequence for FORM(some UI) should get downloaded using service.
Currently, this download is in a BackgroundWorker Thread.
Now, since the performance is slow... We decided to categories the FORMS into 2 and start downloading parallely using another BackgroundWorker on top of the existing Thread.
Now, the scenario is the either of this BackgroundWorker should wait for other to complete.
So, how to implement it.
I tried with AutoResetEvent. but, i could not achieve this.
Any help is appreciated.
I don't think that the scenario is really that one BackgroundWorker should wait for another. What you really want is to fire some UI event after (and only after) both of them complete. It's a subtle but important difference; the second version is a lot easier to code.
public class Form1 : Form
{
private object download1Result;
private object download2Result;
private void BeginDownload()
{
// Next two lines are only necessary if this is called multiple times
download1Result = null;
download2Result = null;
bwDownload1.RunWorkerAsync();
bwDownload2.RunWorkerAsync();
}
private void bwDownload1_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
download1Result = e.Result;
if (download2Result != null)
DisplayResults();
}
private void bwDownload2_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
download2Result = e.Result;
if (download1Result != null)
DisplayResults();
}
private void DisplayResults()
{
// Do something with download1Result and download2Result
}
}
Note that those object references should be strongly-typed, I just used object because I don't know what you're downloading.
This is really all you need; the RunWorkerCompleted event runs in the foreground thread so you actually don't need to worry about synchronization or race conditions in there. No need for lock statements, AutoResetEvent, etc. Just use two member variables to hold the results, or two boolean flags if the result of either can actually be null.
You should be able to use two AutoResetEvent's and the WaitAll function to wait for both to complete. Call the Set function on the AutoResetEvent objects in the respective OnRunWorkerCompleted event.
Jeffrey Richter is THE guru when it comes to multi threading and he's written an amazing library called Power Threading Library which makes doing tasks like downloading n files asynchronously and continuing after they are all completed (or one or some), really simple.
Take a little time out to watch the video, learn about it and you won't regret it. Using the power threading library (which is free and has a Silverlight and Compact Framework version also) also makes your code easier to read, which is a big advantage when doing any async stuff.
Good luck,
Mark
int completedCount = 0;
void threadProc1() { //your thread1 proc
//do something
....
completedCount++;
while (completedCount < 2) Thread.Sleep(10);
//now both threads are done
}
void threadProc2() { //your thread1 proc
//do something
....
completedCount++;
while (completedCount < 2) Thread.Sleep(10);
//now both threads are done
}
Just use 2 BackgroundWorker objects, and have each one alert the UI when it completes. That way you can display a spinner, progress bar, whatever on the UI and update it as download results come back from the threads. You will also avoid any risks of thread deadlocking, etc.
By the way, just so we are all clear, you should NEVER call a blocking function such as WaitAll from the UI thread. It will cause the UI to completely lock up which will make you users wonder WTF is going on :)
Related
I have a main thread that invokes multiple backgroundworkers (in .net/c#).
Each of these threads starts a process in order to run an executable.
When a process ends, I want to tell the main thread to kill all other threads and their respective processes. After all of them stopped, I want to know this and continue to run the main thread for post-processing.
I keep a list of these external processes so I have no problem killing them all. My problem is how to kill all these backgroundworkers. I tried to keep a list of the threads associated with them and kill them from within the first thread that terminates, but apparently this does not kill the backgroundworker itself because the runworkercompleted method is still invoked multiple times.
Does anyone have a pattern on how to kill those workers in a nice way ? should I somehow notify the main thread to do the killing of the other workers ?
I'd recommend using async/await and CancellationTokenSources. I'll give advice on how to use BackgroundWorkers as well, but since async/await is so much more convenient (and shorter), it goes first.
async/await is convenient because it gives you the features you're looking for without much added complexity.
private async void SomeEvent(object sender, EventArgs e)
{
CancellationTokenSource cts = new CancellationTokenSource();
var waiter1 = DoSomething(cts.Token);
var waiter2 = DoSomethingElse(cts.Token);
// etc.
// Wait for the first one to finish, then cancel
await Task.WhenAny(waiter1, waiter2, ...).ConfigureAwait(false);
cts.Cancel();
// wait for the remainder to finish
await Task.WhenAll(waiter1, waiter2, ...).ConfigureAwait(false);
// Do Postprocessing
}
Your "waiters" look something like this:
private async Task DoSomething(CancellationToken token)
{
// Do stuff
// Periodically check if someone has finished
if (Token.IsCancellationRequested)
{
// clean up
return;
}
}
async/await code has a few gotchas, including deadlock. Since this sounds like a quick project (I could be wrong), it seems like a good place to learn - especially if there's no massive codebase to rework. If you want to learn more, I think Stephen Cleary's blog is a good place to start, particularly his intro.
On the other hand, if you're absolutely sure you want to use BackgroundWorkers... well I don't blame you, but I don't envy you either.
First, your workers have to know whether somebody else finished first. Use the finished BackgroundWorker's RunWorkerCompleted method to cancel the others BackgroundWorkers:
private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
// Check for errors...
}
else if (e.Cancelled)
{
// Mark that this one has finished
}
else
{
// Assuming you have a set of BackgroundWorkers called "workers"
foreach (var bgw in workers)
bgw.CancelAsync();
// other stuff...
}
}
Then, add a bit of code at the end of your DoWork method to report the cancellation...
private void DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
// Do stuff...
// When "RunWorkerCompleted" is called, let it know whether this worker has been cancelled.
e.Cancel = worker.CancellationPending;
}
And that's it. You can also check the worker.CancellationPending periodically to see if you can finish earlier, but don't forget to assign worker.CancellationPending to e.Cancel before your return!
One last thing: if you want the postprocessing to continue when all workers have finished (and only then), you need to have a way to mark when a particular worker is finished (to cancel the others), and then a way to find out when they've all finished (so you can begin postprocessing). It's doable, and not too difficult - off the top of my head, I'd use a Dictionary<BackgroundWorker, bool> to indicate which workers have finished. Still, that's another piece of clutter you can avoid with async/await.
From this answer it seems there is no way to kill a Backgroundworker. However this answer shows a workaround by overriding OnDoWork and keeping a reference to Thread.CurrentThread. I would still try to have those Backgroundworkers check for a notification to cancel, though.
I'm not super familiar with multithreading, and want to know if this is the safest way to update the UI thread from a different thread. The workflow of my code is as follows:
// this is the button click action
private async void button_Click(object sender, EventArgs e)
{
//do some things to local variables
await create();
}
// this task creates the thing and does all the heavy processing
public Task create()
{
return Task.Run(() =>
{
try
{
//some code
consoleOut(string);
}
catch (Exception e)
{
//do things
}
}
}
// custom logging that prints formatted stuff out to a ListBox
public void consoleOut(String str)
{
if (this.InvokeRequired)
{
this.Invoke(
new MethodInvoker(
delegate() { consoleOut(str); }));
}
else
{
//print stuff
ListBox.Items.Add(str);
}
}
Is this the safest way to update the contents of my ListBox from create Task?
For reference I combined things from these previous questions, but there wasn't a lot of explanation on what the code did, hence my question about thread safety and if there are better ways:
Make wpf UI responsive when button click is performed
Cross-thread operation not valid
This is how I multithread which has worked 100% great for me... though someone will probably get on here and say it's the worst ever...
//start a second thread with parameters in this case
Thread filterThd = new Thread(() => filterLike(FilterTextBox.Text.ToLower(),column));
filterThd.Start();
//somewhere in your thread, it updates the ui like this
Form2 f2= (Form2)System.Windows.Forms.Application.OpenForms["Form2"];
f2.Invoke((MethodInvoker)(() => f2.DataGrid.DataSource = null));
IMHO, there are two problems with the approach you're taking:
You're overcomplicating things - more on that later,
Depending on what the //some code section does you could end-up with a frozen application.
Now, let's tear each part in its own bits.
The over complication is due to the fact that you're mixing two different ways of doing basically the same thing - namely, the Invoke method and a Task, although the Task-based approach is incomplete.
However, the biggest problem is the part with // some code; as I said before, if that part is heavy on the resources (i.e. takes long to run) you could end up with a frozen application because the thread on which that method is running is the UI thread which consumes the UI resources otherwise allocated for the application to process messages and draw controls.
I would split the code into two logical parts:
one that does the processing and
the other one that logs the string to UI
The code should look like this:
private async void button_Click(object sender, EventArgs e)
{
//do some things to local variables
await Task.Run(() =>
{
// some code
})
.ContinueWith(p => ListBox.Items.Add(str),
TaskScheduler.FromCurrentSynchronizationContext());
}
Aside from removing the clutter the code above splits the work into two tasks which can be scheduled differently: the first one can be executed on a background thread and will not affect the UI while the continuation will run on the UI thread due to the restriction passed via TaskScheduler.FromCurrentSynchronizationContext() allowing you to safely access controls and even though it is executed on the UI thread its execution time is very small thus the application won't freeze.
I have been writing ASP.NET web application for years now, but haven't really worked on large windows forms projects. I now need to work on one, so I am looking on some pointers on how a large windows forms project should ideally be structured. More specifically, I would like to know how to handle multiple threads. Assume you have a process which takes some time to complete - you do not want to have the ui window frozen and not responding. So that logic needs to move in a separate thread. If this thread accesses the UI, then it will cause exceptions. Invoke seems to do the trick, but looks very ugly and cumbersome to write and read!
So, in reality, what are the best practices? What type of threads should one launch, and how should these threads be split between UI and logic? Any sample code to get started?
here is a short way to use the backgroundworker
public Form1()
{
InitializeComponent();
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true; //set to true to fire the progress-changed event
worker.DoWork += doWork;
worker.ProgressChanged += progressChanged;
}
void progressChanged(object sender, ProgressChangedEventArgs e)
{
int progress = e.ProgressPercentage; //Progress-Value
object userState = e.UserState; //can be used to pass values to the progress-changed-event
}
void doWork(object sender, DoWorkEventArgs e)
{
object argument = e.Argument; //Parameters for the call
bool cancel = e.Cancel; //Boolean-Value for cancel work
object result = e.Result; //Object for a return-value
}
As soon as you use a different thread you will have to switch back to the UI thread when touching the UI.
someForm.BeginInvoke() can do this but there are more options.
The BackgroundWorker can do the switching for you.
In .NET 4.5/ C# 5 you can use async/await; the continuation will be called on the original thread.
In general, try to untangle the logic as much as you can from the UI so you do not need to switch thread too often.
There are lots of ways to achieve UI responsiveness, execute long running tasks, achieve parallelism. You have to select the right way for your application -
This article by Jon Skeet is always a bonus to start with.
You can call Synchronous methods Asynchronously using any of these styles as per your application design and requirements
More difficult situations, such as coordinating the work of multiple threads, or handling threads that block
There are a number of ways to expose asynchronous features to client code. Read here for the Event-based Asynchronous Pattern - which prescribes the recommended way for classes to present asynchronous behavior.
Background Worker comes in handy when you have a single long running task.
Hope this gives you a head start.
I have a scenario where I'm doing some Actor-Model kind of messagequeing where I want a method to insert a Task or delegate into a queue (possibly the new ConcurrentQueue) , wait for some other process to process the queue, execute the task and then return the result, preferably without locking. The method might be called both synchronously and asynchronously. Only one queued action might run simultaneously
I can't wrap my head around how to accomplish this in a somewhat performant manner, please help :)
EDIT
Here's an attempt, anyone seeing any problems with this approach (exception handling excluded) ? Also, I can imagine this has quite a lot of overhead compared to simply locking, and how does it compare to for instance using asynchronous delegates?
public partial class Form1 : Form
{
private BlockingCollection<Task<int>> blockingCollection = new BlockingCollection<Task<int>>(new ConcurrentQueue<Task<int>>());
private int i = 0;
public Form1() {
InitializeComponent();
Task.Factory.StartNew(() =>
{
foreach (var task in blockingCollection.GetConsumingEnumerable()) {
task.Start();
task.Wait();
}
});
}
public int Queue() {
var task = new Task<int>(new Func<int>(DoSomething));
this.blockingCollection.Add(task);
task.Wait();
return task.Result;
}
public int DoSomething() {
return Interlocked.Increment(ref this.i);
}
private void button1_Click(object sender, EventArgs e) {
Task.Factory.StartNew(() => Console.Write(this.Queue()));
}
}
The TPL should do that for you - just call Wait() on your Task<T> - however, there is no way to do this without blocking; by definition, in your scenario that is exactly want you want to do. Blocking might be implemented via a lock, but there are other ways too - the TPL hides this. Personally, in a similar scenario I do it with a custom queue and a mini-pool of objects I can use to lock against (never exposed outside the wrapper).
You might also want to look at the C# 5 async/await stuff.
But note: if you aren't going to do anything useful while you are waiting, you might as well run that code directly on the current thread - unless the issue is thread-bound, for example a multiplexer. If you are interested, later today (or over the weekend) I intend releasing the multiplexer that stackoverflow uses to talk to redis, which (in synchronous mode, at least) has exactly the problems you describe.
As a side note; if you can work with a callback (from the other thread), and not have to wait on completion, that can be more efficient overall. But it doesn't fit every scenario.
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.
}