在什么情况下您不使用方法签名中的Task<T>
来返回async
?
我在下面的代码中有这样一种方法,但是在了解发生了什么情况时遇到了麻烦。
为什么下面的示例代码无法通过任何await
语句执行?
即。为什么Console.WriteLine("4)");
和Console.WriteLine("3)");
和return x;
永远不会执行?
class Program
{
static void Main(string[] args)
{
TestAsync testAsync = new TestAsync();
testAsync.Run();
Console.Read();
}
}
public class TestAsync
{
public async void Run()
{
Task<int> resultTask = GetInt();
Console.WriteLine("2)");
int x = await resultTask;
Console.WriteLine("4)");
}
public async Task<int> GetInt()
{
Task<int> GetIntAfterLongWaitTask = GetIntAfterLongWait();
Console.WriteLine("1)");
int x = await GetIntAfterLongWaitTask;
Console.WriteLine("3)");
return x;
}
public Task<int> GetIntAfterLongWait()
{
Task.Run(() =>
{
for (int i = 0; i < 500000000; i++)
{
if (i % 10000000 == 0)
{
Console.WriteLine(i);
}
}
});
Console.WriteLine("Returning 23");
return new Task<int>(() => 23);
}
}
/*
Output is:
Returning 23
1)
2)
<list of ints>
*/
答案 0 :(得分:4)
当您通过非Task
方法返回async
时?
Task<T>
是针对未来值的 promise 通用称呼。无论是从关键字async
的方法还是从另一个源(例如启动的线程或IO回调)产生此承诺,调用者都不会感兴趣,而只是实现策略。这也是为什么接口(或抽象方法定义)根本没有async
关键字(async
/ await
是一种实现策略)的原因。
您的代码示例
GetIntAfterLongWait
有两种缺陷。实例化的第一个实例化Task
并卸载到线程中,但是结果从未被提取(因此从未等待过……也从未延迟任何事情)。GetIntAfterLongWait
中返回的任务)(由具有执行方法的构造函数创建),但未启动(Task.Start()
) 。其他更简单的方法是静态Task.Run
或(在这种情况下)Task.FromResult
。任务(或承诺)从不交付结果,因为构造函数中的功能块从不执行。Main
方法不等待返回任务的结果(通过await
或Task.Wait()
或Task.Result
。 答案 1 :(得分:0)
您可能会在GetIntAfterLongWait()
方法中创建一个新线程。尝试将return new Task<int>(() => 23);
更改为return Task.FromResult(23);
。
有关Task.FromResult
的更多信息,请参见How to: Create Pre-Computed Tasks上的MSDN文档(有一个很好的例子)
答案 2 :(得分:0)
代码中的问题是实际上您await
从未启动过任务,因为方法GetIntAfterLongWait
返回了尚未启动的新任务实例。所以基本上您有一个僵局,等待根本无法开始的事情。
您可以返回Task.FromResult(23)
,该任务基本上已经完成,或者您可以实际运行任务Task.Run<int>(() => 23);