我正在从教程中学习TPL(async / await),我试图使用控制台应用程序自己测试它。请不要被我的无知所冒犯。 我确信我在某处做错了 - 我写了下面的代码:
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;
}
它是普通的C#控制台代码。 我的问题是为什么我得到以下输出:
3/5/2015 5:22:37 PM: Waiting started...
3/5/2015 5:22:37 PM: Waiting ended...
26
&#34;等待开始&#34>之间是否存在相当大的时间差距?和&#34;等待结束&#34;?
更新
在答案之后,我发现Task.Delay(..)和Thread.Sleep(..)并不相同,因为它们的工作方式完全不同。 这是一个很好的link,用一个例子来解释。
将TPL视为多线程的另一个框架似乎是错误的。所有答案都对我有所帮助,所以我投票赞成了所有人。但是,我选择Jon的答案,因为它是最具说明性的,也是第一个出现的答案。 谢谢大家!
答案 0 :(得分:5)
不,因为事实上你在打印Waiting started
之前已经睡了7秒钟。这是发生的事情:
如果您将每个Thread.Sleep
更改为
await Task.Delay(...);
然后你会看到你的期望。新流程将是:
理解这一点非常重要,直到异步方法遇到它实际需要暂停的第一个await
(因为它等待的东西还没有完成),它会同步执行。这不像调用异步方法分成不同的线程。
答案 1 :(得分:3)
这是因为你的方法都不是异步的。他们通过返回Task
假装是异步的,但它们都是同步执行的。
实际上你应该收到IncrementNumber
号码的编译器警告这个异步方法缺少&#39; await&#39;运营商并将同步运行......等等。它基本上说你的方法将同步执行。 This answer explains it in detail
因此,当ProcessNumber
返回整个嵌套方法时,调用已经同步完成。
将方法更改为使用await Task.Delay
而不是Thread.Sleep
来使其异步。
答案 2 :(得分:1)
您需要重构代码。像这样
static async Task<int> IncrementNumber(int j_)
{
await Task.Delay(...);
return (j_ + 23) / 23;
}
如果您发现CPU绑定任务而不是Thread.Sleep,那么您需要执行类似的操作。
//it will create a new thread then sleep.
await Task.Run( () => ( CPUBoundTask());
var integer = await IncrementNumber(i_ * 23);
return integer;