Reputation: 335
in my app I have two methods that load data from csv. These methods are loadData()
and loadOtherData()
. I want to run them in parallel so I have two threads to run them.
The loadData()
method also populate one datagridview, while the data loaded by the loadOtherData()
method are stored in a dictionary myDictionary
.
After data loading is completed (so the methods running in the two threads have finished) I want to call another method updateGrids()
that takes myDictionary
as argument.
For updateGrids()
to run properly, both loadData()
and loadOtherData()
must have run successfully cause otherwise the method doesn't have the data to work on.
How can I call method updateGrids()
only when the other methods have terminated in other threads?
The structure is as follow:
private void loadData_Click_1(object sender, EventArgs e)
{
ThreadStart thread1Start = new ThreadStart(loadData); // load data and fill the first datagridview
ThreadStart thread2Start = new ThreadStart(loadOtherData); // load data and fill myDictionary
Thread t1 = new Thread(thread1Start);
Thread t2 = new Thread(thread2Start);
t1.Start();
t2.Start();
updateGrids(myDictionary); // call this method to update remaining datagridviews
}
private void updateGrids(Dictionary<string, double> myDictionary)
{
// update the remaining datagridviews by using
// information in the first datagridview and in myDictionary
}
But if I run this, I get the error when updateGrids()
since it doesn't have the data to work with. How can I easily change the code to make it work?
Upvotes: 0
Views: 120
Reputation: 8562
After you start your threads, you want to wait until they are done. So add these lines of code:
t1.Join();
t2.Join();
Join will cause the current thread to sleep until the thread being joined is complete.
Based on comments, I'm assuming this is WinForms. In this case Join
will block the UI thread. You could create a third thread that will join the other two threads and then call Invoke to call your update method.
Since you're using .Net 4.5., you could use Async / Await; add the async
modifier to your click method event handler and uses Tasks instead of Threads directly and await
them. Other answers cover that, and you can see this blog for other details too.
Upvotes: -1
Reputation: 15354
You can use async/await to wait both tasks without blocking the UI
async private void loadData_Click_1(object sender, EventArgs e)
{
await Task.WhenAll(Task.Run(() => loadData()),
Task.Run(() => loadOtherData()));
updateGrids(myDictionary);
}
Upvotes: 1
Reputation: 91
You could stop using ThreadStart objects directly and use Tasks instead - have them returned from your loadData and loadOtherData methods.
You have either two options here:
Either Use Task.WaitAll if you're using .NET 4.0
or (more preferable)....
Make loadData and loadOtherData async in .NET 4.5 and above (or use the async BCL package in .NET 4.0). The when you call the methods, you can cache the Task objects they return and await a call to Task.WhenAll
public async Task LoadData(){
}
public async Task LoadOtherData() {
}
private async void loadData_Click_1(object sender, EventArgs e)
{
var loadDataTask = LoadData();
var loadOtherDataTask = LoadOtherData();
await Task.WhenAll(loadDataTask, loadOtherDataTask);
updateGrids(myDictionary);
}
Upvotes: 2