我正试图抓住异步等待模式。按照this示例,我实施了 这个小程序:
private async void asynchWork()
{
// Line 1
Task<string> readTask = asynchAwaitWork();
// Line 2
synchWork();
// Line 3
string result = await readTask;
// Line 4
Debug.WriteLine(result);
Debug.WriteLine("The End");
}
private void synchWork()
{
for (int i = 0; i < 5; i++)
{
Debug.WriteLine("SynchWork For i : " + i);
Thread.Sleep(750);
}
}
private async Task<string> asynchAwaitWork()
{
for (int i = 0; i < 15; i++)
{
Debug.WriteLine("A-SynchWork For i : " + (i+111));
Thread.Sleep(750);
}
return "finished";
}
我预计会执行第1行,然后第2行和第4行必须等到第3行完成并返回一个字符串。
但是查看输出synchWork
方法是在asynchWork
方法之后执行的。
A-SynchWork For i:111
A-SynchWork For i:112
A-SynchWork For i:113
A-SynchWork For i:114
A-SynchWork For i:115
...
A-SynchWork For i:125
SynchWork For i:0
SynchWork For i:1
SynchWork For i:2
SynchWork For i:3
SynchWork For i:4
完成
结束
我希望synchWork
方法在asynchWork
方法出现错误时执行,并在第3行等待结果。
我在这个例子中误解了什么?或者仅仅是Debug.WriteLine
的输出是按顺序执行的,但实际的工作顺序是否符合我的预期?
编辑: 在我学到的评论和答案的帮助下:
不要忽视警告并研究其含义;)
使用await
关键字允许等待由方法内创建的Task
执行的操作的结果。
编辑2:
因为Thread.Sleep(750)
只是一个模拟作品,我真的不需要Delay
这也有效:
private async Task<string> asynchAwaitWork()
{
await Task.Run(()=> {
for (int i = 0; i < 15; i++)
{
Debug.WriteLine("A-SynchWork For i : " + (i+111));
Thread.Sleep(750);
}
});
return "finished";
}
非常感谢你。我学到了很多东西:))
答案 0 :(得分:2)
只关注你的主程序:
当第3行执行时,您可以保证第1行中的任务已完成执行其中的任何内容。
在第2行,您无法保证任务已开始执行或已完成。你不知道它是否会并行运行。所有你知道的是,有一个任务可以安排执行。
您在函数asynchAwaitWork
中创建的任务的实现是完全同步的。该实现细节导致它在返回最终(在这种情况下是立即)返回字符串的Task时完全完成打印。
请注意,您创建的任务不会打印任何内容。在当前实现中打印“A-SynchWork For i”消息是创建任务的副作用。
答案 1 :(得分:1)
只需更换
asynchAwaitWork的Thread.Sleep(750);
到await Task.Delay(750);
事实是asynchAwaitWork开始在主线程中工作。异步工作 - 这是为了延续。使用await关键字,您可以创建continuation,这就是它开始并行工作的原因。
还要将当前线程ID添加到输出中以查看会发生什么。例如:
private async void asynchWork()
{
// Line 1
Task<string> readTask = asynchAwaitWork();
// Line 2
synchWork();
// Line 3
string result = await readTask;
// Line 4
Debug.WriteLine(result);
Debug.WriteLine("The End");
}
private void synchWork()
{
for (int i = 0; i < 5; i++)
{
Debug.WriteLine("SynchWork For i : " + i + " and thareadId = " + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(750);
}
}
private async Task<string> asynchAwaitWork()
{
for (int i = 0; i < 15; i++)
{
Debug.WriteLine("A-SynchWork For i : " + (i + 111) + " and thareadId = " + Thread.CurrentThread.ManagedThreadId);
await Task.Delay(750);
//Thread.Sleep(750);
}
return "finished";
}
正如所注意到的,Task.Delay(750)将使用相同的同步上下文(如果已创建)。 例如,如果您从WPF运行代码
[STAThread]
void Main()
{
var window = new Window();
window.Loaded += (s, e) => {
asynchWork();
};
window.ShowDialog();
}
你会发现所有事情都发生在同一个线程中。
所以,请注意这一点,您可以使用await Task.Delay(750).ConfigureAwait(false);
来避免这种情况。