Roy*_*mir 7 .net c# winforms async-await
看看这段代码:
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;
}
Run Code Online (Sandbox Code Playgroud)
这是一个GUI(Windows窗体)应用程序,这意味着只有一个线程执行每行代码.
BBB(data)无需等待即可快速调用所有调用.每次BBB调用进入BBB method,看await哪些没有完成并返回(返回AAA).
现在,当经过一秒(大约)时,所有延续都发生在GUI线程中.
题
延续不会同时发生,因为它是一个GUI线程.所以先前的声明:
data.Value = data.Value + 1;
Run Code Online (Sandbox Code Playgroud)
一定发生了.
换一种说法 ,
我知道所有BBBs都是以相同的初始值调用的data,但是并发不会同时发生
GUI线程最终必须运行:
继续#1
MessageBox.Show(data.Value.ToString());
data.Value = data.Value + 1; //So this basically should do 0-->1
....
Run Code Online (Sandbox Code Playgroud)
继续#2
MessageBox.Show(data.Value.ToString()); // Why data.Value still "0" ??
data.Value = data.Value + 1;
....
Run Code Online (Sandbox Code Playgroud)
继续#3
MessageBox.Show(data.Value.ToString()); // Why data.Value still "0" ??
data.Value = data.Value + 1;
Run Code Online (Sandbox Code Playgroud)
看起来这些延续不是作为一个整体而是作为共享量子安排的?
这是因为您正在使用MessageBox.Show调试打印并显示模式消息框阻止代码流但不阻止UI线程(否则您无法与消息框交互).
因此,当通过显示消息框来"阻止"第一个延续时,下一个延续可以运行,然后是第三个.它们都被显示消息框"阻止",但UI线程本身却没有.
这就是他们都展示的原因0,只有当你发布消息框时,他们才能继续运行并增加变量.
如果Console.WriteLine在显示消息框之前使用打印值,则可以看到:
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;
}
Run Code Online (Sandbox Code Playgroud)
您会注意到,0在1秒之后所有延续时间打印3次,而不是在您关闭消息框之后.
基本上,continuation同时运行,但不是并行使用相同的线程,因为MessageBox.Show它们在其中.
如果您使用Console.WriteLine而不是MessageBox.Show您将看到该值一次增加一个:
async Task BBB(SharedData data)
{
await Task.Delay(TimeSpan.FromSeconds(1));
Console.WriteLine(data.Value);
data.Value = data.Value + 1;
}
Run Code Online (Sandbox Code Playgroud)
输出:
0
1
2
Run Code Online (Sandbox Code Playgroud)