Recently I've started working with multithreading and have been trying to better understand await/async and Task. I've typed up the following scenario:
private void button1_Click(object sender, EventArgs e)
{
var list = GenerateList();
progressBar1.Maximum = list.Count ();
CreateStuff (list));
MessageBox.Show ("Complete!");
}
async void CreateStuff (List<int> list)
{
//additional Parameters here used for DoWork()
await Task.Run (()=>Parallel.ForEach(list, item =>
{
DoWork();
Invoke(new Action(() => progressBar1.PerformStep()));
}));
//do something that relies on list
}
I'm trying to make the message box appear after the completion of the CreateDocs method. I was told by a peer that it was possible to keep using await async in the CreateStuff() method and still wait until the method is compelte before I show the message box. I've been researching await async and Task for a while and can't seem to figure out how to do this.
To me, it seems much easier to make the button1_Click() use await async, then await the CreateStuff() method.
My question is this: Is it possible to keep using await async in the CreateStuff method and still wait for the completion of the CreateStuff() method in button1_Click() before displaying the message box?
I'm assuming that it has to do with returning the Task, but I can't quite figure out how to progress about it.
Any help is appreciated. Thanks!
My question is this: Is it possible to keep using await async in the CreateStuff method and still wait for the completion of the CreateStuff() method in button1_Click() before displaying the message box?
Absolutely - but you need to change the return type of CreateStuff
first. Currently you're returning void
, which is almost never a good idea - it's really only there for event handlers. All you need to do is change it to return Task
, and you can await it:
async Task CreateStuff (List<int> list)
Then in your click handler (which needs to be async too), await the result of calling it:
await CreateStuff (list);
It's not at all clear that the implementation of CreateStuff
is really ideal, mind you. You don't need an async method for that - you could just have:
Task CreateStuff(List<int> list)
{
return Task.Run(() => Parallel.ForEach(list, item =>
{
DoWork();
Invoke(new Action(() => progressBar1.PerformStep()));
}));
}
There's not a lot of point having an async method which exists just to create a task and await it, when you can just return the task and let the calling code await that instead. (They do behave slightly differently in a few ways, but not in any way which is important in this particular case, I suspect.)
See more on this question at Stackoverflow