[英]Why the async await not working as expected
I am learning TPL (async/await) from a tutorial and I tried to test it out myself using a console application. 我正在从教程中学习TPL(异步/等待),并尝试使用控制台应用程序对其进行测试。 Please don't be offended by my ignorance. 请不要被我的无知所冒犯。 I am sure I am doing wrong somewhere- I wrote the following code: 我确定我在某处做错了-我编写了以下代码:
static void Main(string[] args_)
{
Task<int> task = ProcessNumber(25);
Console.WriteLine(string.Format("{0}: Waiting started...", DateTime.Now));
task.Wait();
Console.WriteLine(string.Format("{0}: Waiting ended...", DateTime.Now));
Console.WriteLine(task.Result);
Console.WriteLine("Press any key to terminate!");
Console.ReadLine();
}
static async Task<int> ProcessNumber(int i_)
{
Thread.Sleep(1000);
var integer = await IncrementNumber(i_ * 23);
return integer;
}
static async Task<int> IncrementNumber(int j_)
{
Thread.Sleep(6000);
return (j_ + 23) / 23;
}
It's plain C# console code. 这是纯C#控制台代码。 My question is why do I get following output: 我的问题是为什么我得到以下输出:
3/5/2015 5:22:37 PM: Waiting started...
3/5/2015 5:22:37 PM: Waiting ended...
26
Shouldn't there be considerable time gap between"Waiting started" and "Waiting Ended"? “等待开始”和“等待结束”之间是否应该有相当长的时间间隔?
UPDATE 更新
After the answers, I figured out that Task.Delay(..) and Thread.Sleep(..) aren't same because they work very differently. 在回答之后,我发现Task.Delay(..)和Thread.Sleep(..)是不一样的,因为它们的工作方式非常不同。 Here is a nice link that explains with an example. 这是一个很好的链接 ,并举例说明。
Seems it would be a mistake to consider TPL as yet another framework for multithreading. 似乎将TPL视为另一种多线程框架是错误的。 All the answers helped me , so I voted for all. 所有的答案对我都有帮助,所以我投了赞成票。 However, I select Jon's answer as it is the most illustrative and the first one to appear. 但是,我选择了乔恩的答案,因为这是最具说明性的,也是第一个出现的答案。 Thanks all! 谢谢大家!
No, because in fact you're sleeping for 7 seconds before you print Waiting started
. 否,因为实际上您在打印“ Waiting started
之前要睡眠7秒钟。 Here's what happens: 这是发生了什么:
If you change each Thread.Sleep
to 如果将每个Thread.Sleep
更改为
await Task.Delay(...);
then you'll see what you expect. 然后您将看到您的期望。 The new flow will be: 新流程将是:
It's really important to understand that until an async method hits the first await
where it actually needs to pause (because the thing it's awaiting hasn't completed), it executes synchronously. 真正重要的是要理解,直到异步方法在实际上需要暂停的第一个await
发生(因为等待状态尚未完成)之前,它才同步执行。 It's not like calling an async method splits off into a different thread. 这不像调用异步方法将其拆分为另一个线程一样。
It is because none of your methods are asynchronous. 这是因为您的方法都不是异步的。 They pretend to be asynchronous by returning Task
but they all execute synchronously. 它们通过返回Task
来伪装成异步的,但是它们都是同步执行的。
In fact you should be getting the compiler warning for IncrementNumber
number saying This async method lacks 'await' operators and will run synchronously... etc . 实际上,您应该收到针对IncrementNumber
号的编译器警告,说明此异步方法缺少'await'运算符,并且将同步运行...等 。 It basically says that your method will be executed synchronously. 它基本上说您的方法将同步执行。 This answer explains it in detail . 这个答案详细解释了 。
So when ProcessNumber
returns the whole nested methods calls are already finished synchronously. 因此,当ProcessNumber
返回时,整个嵌套方法调用已经同步完成。
Change the method to use await Task.Delay
instead of Thread.Sleep
to make it asynchronous. 更改方法以使用await Task.Delay
而不是Thread.Sleep
使其异步。
you need to refactor your code. 您需要重构代码。 like this 像这样
static async Task<int> IncrementNumber(int j_)
{
await Task.Delay(...);
return (j_ + 23) / 23;
}
if you found CPU bound task instead of Thread.Sleep then you need to do something like this. 如果找到CPU绑定任务而不是Thread.Sleep,则需要执行以下操作。
//it will create a new thread then sleep. await Task.Run( () => ( CPUBoundTask()); var integer = await IncrementNumber(i_ * 23); return integer;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.