【发布时间】:2020-09-11 02:06:39
【问题描述】:
我有一个非常简单的程序,如下所示。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Task task = DemoCompletedAsync();
MessageBox.Show("Method returned");
MessageBox.Show("Exiting .....");
}
static async Task<string> DemoCompletedAsync()
{
MessageBox.Show("Before first await");
await Task.Run(() => GetID());
MessageBox.Show("After first await");
return "Demo";
}
public static int GetID()
{
Thread.Sleep(2000);
return 1;
}
}
在没有调试模式的情况下运行程序时,消息框会以正确的顺序出现。
即
“在第一次等待之前”
“方法返回”
“退出......”
“第一次等待之后”
但在调试时,语句会以随机方式执行,不知何故在 MainWindow() 和 DemoCompletedAsync 之间来回切换
框出的消息以下列方式显示:
“在第一次等待之前”——来自DemoCompletedAsync
“方法返回”---来自MainWWindow
“第一次等待之后”——来自DemoCompletedAsync
“退出……”——来自MainWindow
根据理论,在方法名称中使用 async 关键字告诉编译器该方法将等待使用 await 关键字的异步操作,并且一旦遇到 await 关键字,控制就会传递调用代码。但是,由 await 关键字表示的异步操作将继续执行。一旦异步操作结束,方法的其余部分将被执行。那么为什么我会出现这种奇怪的行为,例如一些语句从MainWindow 执行,一些语句从DemoCompletedAsync 相互切换。我还观察到另一个与消息框相关的问题。 MessageBox.Show 是模态对话框。第二个不应该出现,直到第一个关闭。但在给定程序的情况下,当控制在MainWindow 和DemoCompletedAsync 之间切换时,我实际上同时得到了两个消息框。
【问题讨论】:
-
消息框“任务已完成”显示在刚刚创建任务但尚未等待的位置。所以这个信息是骗人的。我建议在消息中包含
task.Status。 -
你实际上并没有在等待任务,因为你的主要方法没有等待它,所以消息会立即显示,你到底想做什么?这只是一个任务实验?
-
@Charleh 是的,我正在试验任务。是的,消息将立即显示。但它们应该按顺序显示,即来自
MainWindow的消息或来自DemoCompletedAysnc的消息。为什么有些消息显示来自MainWindow,然后来自DemoCompletedAsync,又来自MainWindow。来自MainWindow的消息应按顺序显示。
标签: c# asynchronous async-await