问题
i have two background threads
Worker = new BackgroundWorker();
Worker.DoWork += new DoWorkEventHandler(GetQuery);
Worker.RunWorkerCompleted += GetQuery_RunWorkerCompleted;
Worker.RunWorkerAsync();
Worker2012 = new BackgroundWorker();
Worker2012.DoWork += new DoWorkEventHandler(GetQuery2012);
Worker2012.RunWorkerCompleted += GetQuery2012_RunWorkerCompleted;
Worker2012.RunWorkerAsync();
both the methods in worker threads are returning data tables
now my task is i need to merge those two data tables into one
for that reason i am doing this in the RunCompletion of the first task
void GetQuerys_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
do{} while(Worker2012.IsBusy);
//Merge Datatables
}
but for some reason the do while loop seems to be in infinite loop. the thread does not end. can some one tell me what i am doing wrong. or is there a better way to wait for the second worker thread to get complete so that i can merge data. any help would be appreciated
回答1:
Now that .NET 4.5 is out, I recommend that everyone use Task.Run
instead of BackgroundWorker
, as such:
var task1 = Task.Run(() => GetQuery());
var task2 = Task.Run(() => GetQuery2012());
var dataTables = await Task.WhenAll(task1, task2);
// Merge databases
Task.Run
is superior to BackgroundWorker
in every way, and this is particularly noticeable when doing anything complex (i.e., coordinating two background operations).
回答2:
I'd recommend using TPL instead, making it much more readable:
Task query1 = GetQuery();
Task query2 = GetQuery2012();
Task.WhenAll(query1, query2).ContinueWith( t => {
//merge
});
You can also do await Task.WhenAll()...
if you want the main thread to (asynchronously) wait for the tables to be merged.
Make sure you change your Query
methods to something like this:
public Task GetQuery() {
return Task.Run( () => {
//do background work
});
}
Edit I just noticed something that might go wrong with this.
The ContinueWith task will (most likely) not run in the UI thread.
If you need to merge the tables in the UI thread, then you should do this instead:
public void UIMethod() {
Task query1 = GetQuery();
Task query2 = GetQuery2012();
await Task.WhenAll(query1, query2); //will free the thread until both tasks complete
MergeTables();
}
This way, the MergeTables()
method will run on the UI thread.
来源:https://stackoverflow.com/questions/18659124/merging-the-results-of-two-background-workers-upon-completion