C# 行为异步等待控制台应用程序与WPF
我对async Wait很陌生。我想我理解了控制台应用程序的示例。当将相同的代码传输到WPF时,会出现死锁,我不知道确切原因C# 行为异步等待控制台应用程序与WPF,c#,wpf,asynchronous,async-await,deadlock,C#,Wpf,Asynchronous,Async Await,Deadlock,我对async Wait很陌生。我想我理解了控制台应用程序的示例。当将相同的代码传输到WPF时,会出现死锁,我不知道确切原因 // All as expected // Output: // LongOperationAsync Start // Before task.Wait(); // LongOperationAsync End // After task.Wait(); // Result: 4711 class Program { public static void Ma
// All as expected
// Output:
// LongOperationAsync Start
// Before task.Wait();
// LongOperationAsync End
// After task.Wait();
// Result: 4711
class Program {
public static void Main() {
Task<int> task = LongOperationAsync();
//Console.ReadKey();
Console.WriteLine("Before task.Wait();");
task.Wait();
Console.WriteLine("After task.Wait();");
var result = task.Result;
Console.WriteLine("Result: {0}", result);
Console.ReadKey();
}
static async Task<int> LongOperationAsync() {
Console.WriteLine("LongOperationAsync Start");
await Task.Delay(1000);
Console.WriteLine("LongOperationAsync End");
return 4711;
}
}
下面是阻塞WPF代码:
// WPF handler Output:
// LongOperationAsync Start
// Before task.Wait(); => Blocking
private void button2_Click(object sender, EventArgs e) {
Task<int> task = LongOperationAsync();
Debug.WriteLine("Before task.Wait();");
task.Wait();
Debug.WriteLine("After task.Wait();");
var result = task.Result;
Debug.WriteLine("Result: {0}", result);
}
private async Task<int> LongOperationAsync() {
Debug.WriteLine("LongOperationAsync Start");
await Task.Delay(1000);
Debug.WriteLine("LongOperationAsync End");
return 4711;
}
这两种情况下的代码都会阻塞。这两个例子都不好。两者都不是异步执行的 正确的控制台代码应为:
public static async Task Main()
{
Console.WriteLine("Before LongOperationAsync");
int result = await LongOperationAsync();
Console.WriteLine("After LongOperationAsync");
Console.WriteLine("Result: {0}", result);
Console.ReadKey();
}
private async void button2_Click(object sender, EventArgs e)
{
Debug.WriteLine("Before LongOperationAsync");
int result = await LongOperationAsync();
Debug.WriteLine("After LongOperationAsync");
Debug.WriteLine("Result: {0}", result);
}
等效的WPF代码为:
public static async Task Main()
{
Console.WriteLine("Before LongOperationAsync");
int result = await LongOperationAsync();
Console.WriteLine("After LongOperationAsync");
Console.WriteLine("Result: {0}", result);
Console.ReadKey();
}
private async void button2_Click(object sender, EventArgs e)
{
Debug.WriteLine("Before LongOperationAsync");
int result = await LongOperationAsync();
Debug.WriteLine("After LongOperationAsync");
Debug.WriteLine("Result: {0}", result);
}
async是允许使用wait关键字的语法糖。wait异步地等待已经异步的操作,比如Task。延迟完成,而不阻塞原始线程。异步操作完成后,wait将在原始同步上下文中恢复执行。在WPF应用程序中,这就是UI线程。这就是允许在等待后更新UI的原因
async void仅适用于事件处理程序,如button2\u click。在所有其他情况下,应使用异步任务。异步void方法不能等待,应用程序无法知道它们是否完成 两种情况下的代码块。这两个例子都不好。两者都不是异步执行的 正确的控制台代码应为:
public static async Task Main()
{
Console.WriteLine("Before LongOperationAsync");
int result = await LongOperationAsync();
Console.WriteLine("After LongOperationAsync");
Console.WriteLine("Result: {0}", result);
Console.ReadKey();
}
private async void button2_Click(object sender, EventArgs e)
{
Debug.WriteLine("Before LongOperationAsync");
int result = await LongOperationAsync();
Debug.WriteLine("After LongOperationAsync");
Debug.WriteLine("Result: {0}", result);
}
等效的WPF代码为:
public static async Task Main()
{
Console.WriteLine("Before LongOperationAsync");
int result = await LongOperationAsync();
Console.WriteLine("After LongOperationAsync");
Console.WriteLine("Result: {0}", result);
Console.ReadKey();
}
private async void button2_Click(object sender, EventArgs e)
{
Debug.WriteLine("Before LongOperationAsync");
int result = await LongOperationAsync();
Debug.WriteLine("After LongOperationAsync");
Debug.WriteLine("Result: {0}", result);
}
async是允许使用wait关键字的语法糖。wait异步地等待已经异步的操作,比如Task。延迟完成,而不阻塞原始线程。异步操作完成后,wait将在原始同步上下文中恢复执行。在WPF应用程序中,这就是UI线程。这就是允许在等待后更新UI的原因
async void仅适用于事件处理程序,如button2\u click。在所有其他情况下,应使用异步任务。异步void方法不能等待,应用程序无法知道它们是否完成 在您的示例中,您可以将按钮单击修改为异步。您的任务被阻塞,因为您从未启动过他,您无法在未启动任务的情况下通过等待呼叫 下面是修改后的按钮单击方法
private async void button2_Click(object sender, EventArgs e)
{
var result = await LongOperationAsync();
Debug.WriteLine("Result: {0}", result);
}
在您的示例中,您可以将按钮单击修改为异步。您的任务被阻塞,因为您从未启动过他,您无法在未启动任务的情况下通过等待呼叫 下面是修改后的按钮单击方法
private async void button2_Click(object sender, EventArgs e)
{
var result = await LongOperationAsync();
Debug.WriteLine("Result: {0}", result);
}
这两种情况下的代码都会阻塞。这两个例子在异步世界中都很糟糕,您永远不应该执行任何task.Wait或task.Result的操作。这方面的信息太多,无法回答。这是一个广泛的话题,我所能建议的就是继续做更多的研究。阅读同步上下文,阅读死锁,查找斯蒂芬·克利里(stephen cleary)的博客,利用谷歌,你会到达目的地。我认为你可以阅读这篇文章。尽管建议多读一些是公平的建议,但我认为我们可以做得更好。Panagiotis发布的代码几乎与我要发布的代码一模一样,我认为显示正确的代码非常有用。这两种情况下的代码都会阻塞。这两个例子在异步世界中都很糟糕,您永远不应该执行任何task.Wait或task.Result的操作。这方面的信息太多,无法回答。这是一个广泛的话题,我所能建议的就是继续做更多的研究。阅读同步上下文,阅读死锁,查找斯蒂芬·克利里(stephen cleary)的博客,利用谷歌,你会到达目的地。我认为你可以阅读这篇文章。尽管建议多读一些是公平的建议,但我认为我们可以做得更好。Panagiotis发布的代码几乎与我要发布的代码完全相同,我认为显示正确的代码非常有用。您可以等待任务的完成。var结果=等待长时间操作同步@安迪,我知道。但我必须从代码开始。OP在这一点上确实对更基本的问题感到困惑。我认为最好强调任务不是某种类或对象。你可以等待任务。var结果=等待长时间操作同步@安迪,我知道。但我必须从代码开始。OP在这一点上确实对更基本的问题感到困惑。我认为最好强调任务不是某种类或对象,任务已经开始了。实际的异步任务是由task.Delay生成的。等待不启动任何东西,它等待已经执行的任务任务任务已经启动。实际的异步任务是由task.Delay生成的。等待不启动任何东西,它等待已经执行的任务