I have this code which seems pretty straightforward but the AutoResetEvent never gets signalled. Nothing seems to get returned from the web services and the WaitAll just times out after ten seconds. Everything works fine without the threading jiggerypokery so its not a web service issue. What am I doing wrong?
AutoResetEvent[] autoEvents;
ObservableCollection<Tx3.ResourceService.ResourceTime> resourceTime;
ObservableCollection<Tx3.ResourceService.ResourceTimeDetail> resourceTimeDetail;
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
autoEvents = new AutoResetEvent[]
{
new AutoResetEvent(false),
new AutoResetEvent(false),
};
var resourceService = getResourceServiceClient();
// Get ResourceTime data for this user
resourceService.ListResourceTimeAsync(CategoryWorkItemId, ResourceId);
resourceService.ListResourceTimeCompleted += new EventHandler<Tx3.ResourceService.ListResourceTimeCompletedEventArgs>(resourceService_ListResourceTimeCompleted);
// Get ResourceTimeDetails
resourceService.ListResourceTimeDetailAsync(CategoryWorkItemId, ResourceId);
resourceService.ListResourceTimeDetailCompleted += new EventHandler<ListResourceTimeDetailCompletedEventArgs>(resourceService_ListResourceTimeDetailCompleted);
WaitHandle.WaitAll(autoEvents, 10000);
System.Diagnostics.Debug.WriteLine("do something with both datasets");
}
void resourceService_ListResourceTimeCompleted(object sender, Tx3.ResourceService.ListResourceTimeCompletedEventArgs e)
{
resourceTime = e.Result;
autoEvents[0].Set();
}
void resourceService_ListResourceTimeDetailCompleted(object sender, ListResourceTimeDetailCompletedEventArgs e)
{
resourceTimeDetail = e.Result;
autoEvents[1].Set();
}
I can offer a naive first guess: it looks like you're adding the event handlers after calling the methods that start the asynchronous operations; it's possible there's a race condition in there or some other issue. Could you switch the order of operations so you attach the event handler, and then begin the operation?
These are AutoResetEvent objects -- looks like you want a ManualResetEvent -- the auto version triggers anything waiting, but immediately resets. Manual ones stay triggered so if the callback happens before you get to the WaitAll, it'll just fall through immediately.
Also, qid is correct -- you're attaching your event handlers too late too...so there's two different bugs going on here.
Are you using this code on a thread that is marked with the STA attribute, for example the main UI thread? If so, the WaitAll method is not supported on these threads.
Check here.
Related
I am confused with scenario which I have encountered with cross thread access. Here is what I am trying to do:
Main UI thread - menu item click I create a background worker and run it asynchronously
private void actionSubMenuItem_Click(object sender, EventArgs e)
{
ToolStripMenuItem itemSelected = (ToolStripMenuItem)sender;
ExecuteTheActionSelected(itemSelected.Text);
}
The method ExecuteTheActionSelected is as follows:
private void ExecuteTheActionSelected(string actionSelected)
{
BackgroundWorker localBackgroundWorker = new BackgroundWorker();
localBackgroundWorker.DoWork += new DoWorkEventHandler(localBackgroundWorker_DoWork);
localBackgroundWorker.RunWorkerAsync(SynchronizationContext.Current);
}
The localBackgroundWorker_DoWork has:
ActionExecutionHelper actionExecutioner = new ActionExecutionHelper()
actionExecutioner.Execute();
The Execute method in that class that has method invoker which infact invokes the event handler in UI thread:
public void Execute()
{
// ---- CODE -----
new MethodInvoker(ReadStdOut).BeginInvoke(null, null);
}
protected virtual void ReadStdOut()
{
string str;
while ((str = executionProcess.StandardOutput.ReadLine()) != null)
{
object sender = new object();
DataReceivedEventArgs e = new DataReceivedEventArgs(str);
outputDataReceived.Invoke(sender, e);
//This delegate invokes UI event handler
}
}
The UI event handler is as follows:
private void executionProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (_dwExecuteAction != null)
{
_dwExecuteAction.ShowDataInExecutionWindow(e.Text);
}
}
Now here comes the cross thread issue:
public void ShowDataInExecutionWindow(string message)
{
if (rchtxtExecutionResults.InvokeRequired)
{
rchtxtExecutionResults.Invoke(new ShowDataExecutionDelegate(ShowDataInExecutionWindow), message);
}
else
{
this.rchtxtExecutionResults.AppendText(message + Environment.NewLine);
}
}
Here Invoke doesn't block the UI where as BeginInvoke blocks.
Please help me understand this scenario as i m confused a lot.
Yes, this is normal. The benefit you get out of Invoke() is that it blocks the worker thread. When you use BeginInvoke() the thread keeps motoring and issues invoke requests at a rate higher than the UI thread can handle. It depends on what you ask the UI thread to do but it starts to become a problem around 1000 invokes per second.
The UI thread stops being responsive in this scenario, it is constantly finding another invoke request back while it pumps the message loop and doesn't get around doing its regular duties anymore. Input and paint requests no longer get processed.
The clear source of the problem is the invoke request on every single line of output retrieved from the process. It is just generating them too quickly. You need to fix this by lowering the rate at which you invoke. There's a simple rule for that, you are only trying to keep a human occupied, invoking more than 25 times per second turns whatever you produce in but a blur to the eye. So buffer the lines and measure the amount of time that has passed since the last invoke call.
Also note that using Invoke() is an easy workaround but it isn't exactly guaranteed to work. It is a race, the worker thread could potentially always call the next Invoke() a wee bit earlier than the main thread re-entering the message loop and reading the next message. In which case you will still have the exact same problem.
I have a method which is rebuilding the product catalog of a webshop. This is neccessary after I change some product information. After the rebuilding method I would like to start a second method to generate full text index of the webshop. I can watch the status of the first method (RebuildCatalog). If the status is "RebuildFinished" then I would like to start the second method (GenerateFullTextIndex). I would like to use Threads functionality. Does someone can create an example of how to implementate this scenario?
I would like to use Threads functionality.
It really doesn't sound like you do. Starting one method after another finishes is as simple as:
var status = RebuildCatalog();
if (status == Status.RebuildFinished)
{
GenerateFullTextIndex();
}
No threading required. If you really think you need multiple threads, you should explain why you think they'll help. At what point do you need to perform multiple tasks concurrently?
Well, if you want to use a multiple threads and oranize your calls in chain so they are executed on another thread, but in sequence, and you are using .NET Framework 4.0>, you can use a Task Parallelism, like for example using Task::ContinueWith method.
Example (preudocode from MSDN):
Task<byte[]> getData = new Task<byte[]>(() => GetFileData());
Task<double[]> analyzeData = getData.ContinueWith(x => Analyze(x.Result));
Task<string> reportData = analyzeData.ContinueWith(y => Summarize(y.Result));
getData.Start();
//or...
Task<string> reportData2 = Task.Factory.StartNew(() => GetFileData())
.ContinueWith((x) => Analyze(x.Result))
.ContinueWith((y) => Summarize(y.Result));
Using events would seem to be simpler than watching the status.
In your rebuild catalog code fire a "finished" event on completion:
public event EventHandler<EventArgs> RebuildFinished;
private void Rebuild(...)
{
// Rebuild the catalog
this.RebuildFinished(this, new EventArgs(...));
}
Then handle it:
this.catalog.RebuildFinished += this.RebuildFinished;
private void RebuildFinished(object sender, EventArgs e)
{
// Rebuild the index
}
Now both of these can (and probably should) be using threads to ensure that the UI of your application stays responsive:
this.catalogThread = new Thread(new ThreadStart(this.catalog.Rebuild));
As I can assume from your question your rebuilding method probably takes up considerable time and that is why you want to run in a separate thread. Therefore I would suggest implementing Event based async pattern. When your rebuilding (async) method finishes it will throw finished event with AsyncCompletedEventArgs (which you can subclass to pass your result status) and from there you will start your second method.
BackgroundWorker bw1 = new BackgroundWorker();//To rebuild catalog.
BackgroundWorker bw2 = new BackgroundWorker();//To generate text.
public Form1()
{
InitializeComponent();
bw1.DoWork += bw1_DoWork;
bw1.RunWorkerCompleted += bw1_RunWorkerCompleted;
bw2.DoWork += bw2_DoWork;
bw2.RunWorkerCompleted += bw2_RunWorkerCompleted;
bw1.RunWorkerAsync();//Start new thread. - Rebuild catalog.
}
void bw1_DoWork(object sender, DoWorkEventArgs e)
{
//Rebuild catalog.
}
void bw1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
bw2.RunWorkerAsync();//Generate text.
}
void bw2_DoWork(object sender, DoWorkEventArgs e)
{
//Generate text.
}
void bw2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//Whatever...
}
I'm trying to use a Background Worker in a WPF application. The heavy lifting task uses WebClient to download some HTML and parse some info out of it. Ideally I want to do that downloading and parsing without locking the UI and placing the results in the UI once it's done working.
And it works fine, however, if I quickly submit the "download and parse" command, I get the error:
This BackgroundWorker is currently busy and cannot run multiple tasks
concurrently
So I did some Googling and it seems that I can enable the .WorkerSupportsCancellation property of the background worker and just .CancelAsync(). However, this doesn't work as expected (canceling the current download and parse).
I still get the above error.
Here's my code:
//In window constructor.
_backgroundWorker.WorkerSupportsCancellation = true;
_backgroundWorker.DoWork += new DoWorkEventHandler(_backgroundWorker_DoWork);
_backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_backgroundWorker_RunWorkerCompleted);
//Declared at class level variable.
BackgroundWorker _backgroundWorker = new BackgroundWorker();
//This is the method I call from my UI.
private void LoadHtmlAndParse(string foobar)
{
//Cancel whatever it is you're doing!
_backgroundWorker.CancelAsync();
//And start doing this immediately!
_backgroundWorker.RunWorkerAsync(foobar);
}
POCOClassFoo foo = new POCOClassFoo();
void _backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//This automagically sets the UI to the data.
Foo.DataContext = foo;
}
void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
//DOING THE HEAVY LIFTING HERE!
foo = parseanddownloadresult()!
}
Calling CancelAsync will still fire the RunWorkerCompleted event. In this event, you need to make sure that CancelAsync has not been called, by checking e.Cancelled. Until this event fires, you cannot call RunWorkerAsync.
Alternatively, I would recommend you do what Tigran suggested and create a new BackgroundWorker each time.
Further more, I would recommend storing the results of_backgroundWorker_DoWork in e.Result, then retrieve them from the same in _backgroundWorker_RunWorkerCompleted
Maybe something like this
BackgroundWorker _backgroundWorker;
private BackgroundWorker CreateBackgroundWorker()
{
var bw = new BackgroundWorker();
bw.WorkerSupportsCancellation = true;
bw.DoWork += _backgroundWorker_DoWork;
bw.RunWorkerCompleted += new _backgroundWorker_RunWorkerCompleted;
return bw.
}
private void LoadHtmlAndParse(string foobar)
{
//Cancel whatever it is you're doing!
if (_backgroundWorer != null)
{
_backgroundWorker.CancelAsync();
}
_backgroundWorker = CreateBackgroundWorker();
//And start doing this immediately!
_backgroundWorker.RunWorkerAsync(foobar);
}
//you no longer need this because the value is being stored in e.Result
//POCOClassFoo foo = new POCOClassFoo();
private void _backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
//Error handling goes here.
}
else
{
if (e.Cancelled)
{
//handle cancels here.
}
{
//This automagically sets the UI to the data.
Foo.DataContext = (POCOClassFoo)e.Result;
}
}
private void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
//DOING THE HEAVY LIFTING HERE!
e.Result = parseanddownloadresult()!
}
The thing is that CancelAsync() does what it climes: cancel in async way. That means that it will not stop immediately, but after some time. That time can never be calculated or predicted, so you have a couple of options:
Wait until this backround worker stops really, by waiting in cycle until IsBusy property of it becomes false
Or, I think, better solution is to start another background worker, considering that request of cancelation was already sent to the first one, so it will be soon or later stop. In this case, you need to know from which background worker data comes, in order to process it or not, cause on start of second the first one will still run and pump the data from WebService.
Hope this helps.
CancelAsync returns before the worker cancels and stops its work. Hence, your RunWorkerAsync call is starting before the worker is ready, and you're getting that error. You'll need to wait for the worker to be ready first.
When I'm not interested in tracking progress of an async operation, I tend to prefer to just slap a lambda at ThreadPool.QueueUserWorkItem instead of instantiating and setting up a background worker that I have to check the state of to be able to reuse in a sane way.
You need to verify before you kicks in.
f( !bw.IsBusy )
bw.RunWorkerAsync();
else
MessageBox.Show("Can't run the bw twice!");
You are calling CancelAsync without waiting for the background worker to actually cancel the work. Also you must have your own logic for cancelling the work. There is a good example on MSDN which shows how to do it. Basically in your parseanddownloadresult() method you need to check the CancellationPending property.
How I can aware of a Task finished ?I want a thing like RunWorkerCompleted event in BackGroundWorker.
thanks
You can use ContinueWhenAll, So you will be notified when all processes finished.
Task.Factory.ContinueWhenAll(myTasks, _ => OnAllTasksFinished());
private void OnAllTasksFinished()
{
MessageBox.Show("Finished!");
}
I am calling multithread method from task(in the end)
Pattern multithrea method:
private void SomeEventHandler(object sender, EventArgs e)
{
MethodInvoker method = delegate
{
uiSomeTextBox.Text = "some text";
};
if (InvokeRequired)
BeginInvoke(method);
else
method.Invoke();
}
You can safe work with WFA like in bacroundWorker
When algorithm in BackGrounWorker come to return, he generate event about end of work. But thread object can still continue to exist. It's inner singularity Windows and CLR, - Threads that may exist for some time after death.
I have a method. I want to return a value not from the main thread but from separate thread. Can you give example of it?
Easiest way is to check out the Background Worker
//set up your BackgroundWorker
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.RunWorkerAsync();
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Result != null)
{
//process your e.Result
}
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
//do your work here
e.Result = "testing"; //set the result to any object
}
Your question does not make sense. A method returns a value directly to the method that called it, on the same thread.
EDIT: If you want a method to supply a value to the UI thread on WinForms, you can call the BeginInvoke method. For example,
//In some event handler, such as button1_Click:
ThreadPool.QueueUserWorkItem(delegate {
//This code runs on a background thread.
//In it, you can do something that takes
//a long time without freezing the UI. If
//you need to interact with the UI from
//the background thread, use the Invoke
//method, like this:
var text = (string)Invoke(new Func<string>(() => textBox1.Text));
//I assume you'd want to do something more meaningful.
var result = text + Environment.NewLine + new String(text.Reverse().ToArray());
//To send the result back to the UI thread, call BeginInvoke:
BeginInvoke(new Action(delegate {
//This code is back on the UI thread,
//but it can still use the variables
//defined earlier.
label1.Text = result;
});
});
Jon Skeet has an excellent article on threading within .net in general. However, if you would like a more specific answer to a more specific problem, please post more details.
EDIT:
To make have methods return in a thread other than the main thread, all you need is a second thread. Everything done in that thread will be method calls and returns in that separate thread. Passing data between threads is a much more complex and trick subject. As a starting point, again I point to Jon Skeet's article to get a good base understanding. Beyond that, there are general principles that can be helpful, like Asynchronous calls and BackgroundWorkers (also see here)that can be very helpful, but these are only options, there many ways to do this, and how it should be done is very dependent on the situation.
In order for your method to return something from another thread, that other thread must "have" the something, and must indicate that the "something" is ready to be returned. There is no general case of this, but there are specific cases. For instance, a producer/consumer problem where your other thread produces something and puts it into a queue, and the first thread waits until there's something in the queue, takes it out, then returns it.
Another case that makes a little sense is seen in asynchronous ASP.NET pages. The page starts its life normally, issues one or more asynchronous operations, and then returns back to ASP.NET. It does nothing else until all the asynchronous operations have completed. Then, ASP.NET calls a method in the page that retrieves the results of these operation and uses them in the rest of the page.
You may be able to see that these two cases are very different. That's because you seem to have asked a "learning" question that amounts to "I wonder if a method always has to get its return value from the same thread?" But that's not something you ever have to do in real life, not really.
I will add that the Ada programming language includes something like this - someone who's actually used it will have to say whether it was useful. If I recall correctly, one task can rendezvous with another, and pass data between them.
This does what you asked for:
class DoSomething
{
string result;
public void RunAsync()
{
var t = new BackgroundWorker();
t.DoWork += (sender, e) =>
{
result = string.Empty; // your code goes here instead of string.empty
};
t.RunWorkerCompleted += Finished;//BackgroundWorkerFinished(sender, e);
t.RunWorkerAsync();
}
public void Finished(object sender, RunWorkerCompletedEventArgs e)
{
//result has been set, now what?
}
}
Once you get that down this becomes more useful:
public static void RunAsync(this Action ActionToAsync, Action<object, RunWorkerCompletedEventArgs> FinishedAction)
{
var t = new BackgroundWorker();
t.DoWork += (sender, e) => ActionToAsync();
t.RunWorkerCompleted += (sender, e) => FinishedAction.Invoke(sender,e);//BackgroundWorkerFinished(sender, e);
t.RunWorkerAsync();
}