Looking at this code :
public class SharedData
{
public int Value { get; set; }
}
void button1_Click(object sender, EventArgs e)
{
AAA();
}
async Task BBB(SharedData data)
{
await Task.Delay(TimeSpan.FromSeconds(1));
MessageBox.Show(data.Value.ToString()); //<---- I always see 0 here,
data.Value = data.Value + 1;
}
async Task<int> AAA()
{
SharedData data = new SharedData();
var task1 = BBB(data);
var task2 = BBB(data);
var task3 = BBB(data);
await Task.WhenAll(task1, task2, task3);
MessageBox.Show(data.Value.ToString()); //<--- this does show 3
return data.Value;
}
This is a GUI (windows forms ) application , which means that there is only one thread executing each line of code.
All BBB(data)
invocations are invoked very quick without waiting.
Each BBB
invocation get's into the BBB method
, sees await
which doesn't complete and returns ( to AAA).
Now , when one second (approx) is elapsed, all continuations are happening in the GUI thread.
Question
Continuations doesn't happen simultaneously because it's a GUI thread . So a previous statement of :
data.Value = data.Value + 1;
Must have occurred.
In other words ,
I know that all BBB
s are invoked with the same initial value of data
, but the continuations doesn't happens concurrently
The GUI thread must run eventually:
continuation #1
MessageBox.Show(data.Value.ToString());
data.Value = data.Value + 1; //So this basically should do 0-->1
....
continuation #2
MessageBox.Show(data.Value.ToString()); // Why data.Value still "0" ??
data.Value = data.Value + 1;
....
continuation #3
MessageBox.Show(data.Value.ToString()); // Why data.Value still "0" ??
data.Value = data.Value + 1;
It looks like the continuations are scheduled not as a whole but as shared quanta ?
That happens because you're using MessageBox.Show
for debug prints and showing a modal message box blocks the code-flow but doesn't block the UI thread (otherwise you couldn't interact with the message box).
So, when the first continuation is "blocked" by showing a message box the next continuation can run and then the third. They are all "blocked" by showing the message boxes but the UI thread itself isn't.
That's why they all show 0
and only when you release the message boxes they can continue running and increase the variable.
You can see that if you print the value using Console.WriteLine
before showing the message box:
async Task BBB(SharedData data)
{
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine(data.Value);
MessageBox.Show(data.Value.ToString());
data.Value = data.Value + 1;
}
You'll notice that 0
is printed 3 times by all the continuations exactly after 1 second and not after you dismiss the message boxes.
Basically, the continuations run concurrently, but not in parallel using the same thread because of the MessageBox.Show
in them.
If you use Console.WriteLine
instead of MessageBox.Show
you will see that the value is incremented one at a time:
async Task BBB(SharedData data)
{
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine(data.Value);
data.Value = data.Value + 1;
}
Output:
0
1
2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With