我正在尝试学习异步/等待并创建了以下测试代码,但是它正在同步运行,我不确定为什么。
class Program
{
static void Main()
{
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;//Expecting execution to go back to Run() since it's not done yet.
Console.WriteLine("3)");
return x;
}
public async Task<int> GetIntAfterLongWait()
{
for (int i = 0; i < 500000000; i++)
{
if (i % 10000000 == 0)
{
Console.WriteLine(i);
}
}
return 23;
}
}
输出为:
<long list of ints>
1)
3)
2)
4)
我希望是
<long list of ints>
1)
2)
3)
4)
1)
位于一长串整数中。
为什么要同步运行?
答案 0 :(得分:3)
令人困惑的是,async
关键字不会使您的方法神奇地异步化。相反,您可以考虑将async
方法用作状态机的设置(请参见详细说明here),在该方法中,您可以通过await
调用来调度操作链。
因此,您的异步方法必须尽快执行。在这种设置方法中请勿执行任何阻止操作。您的GetIntAfterLongWait
方法是一个阻塞操作,由于它不包含任何await
,因此在调用该方法时,整个内容将立即执行(没有任何await
的方法为异步继续设置)。对此也必须有警告。
如果您有要在async方法中执行的阻止操作,则可能的选择是通过await Task.Run(() => MyLongOperation());
调用来安排它。
因此,例如,下面的示例将立即返回,因为在第一个await
之前无需执行任何操作。内部等待的任务完成后,return语句将作为继续执行异步执行:
public async Task<int> GetIntAfterLongWait()
{
await Task.Run(() =>
{
for (int i = 0; i < 500000000; i++)
{
if (i % 10000000 == 0)
{
Console.WriteLine(i);
}
}
});
return 23;
}
有关更多详细信息,请参见上面的链接。
更新:
此版本将打印:
1)
2)
<long list of ints> - but 0 can be before even 1) as Task.Run uses another thread
3)
4)