Task.Delay()和新任务(()=> Thread.Sleep())之间的区别
我正在整理一个小小的演示,以便使用Thread.Sleep()
模拟一个长时间运行的方法,并希望添加异步以轻松地从同步过程转到异步过程。 这是初始代码:
private void button1_Click(object sender, EventArgs e) { LongProcess(); } private void LongProcess() { for (int i = 0; i < 33; i++) { progressBar1.Value += 3; Thread.Sleep(1000); } progressBar1.Value += 1; }
我以为我可以简单地将Thread.Sleep(1000)
更改为new Task(()=>Thread.Sleep(1000))
,如下所示:
private void button1_Click(object sender, EventArgs e) { LongProcess(); } private async void LongProcess() { for (int i = 0; i Thread.Sleep(1000)); } progressBar1.Value += 1; }
然而,在第一次等待之后,这永远不会返回到循环。 如果我将Thread.Sleep更改为Task.Delay一切正常,但我不明白为什么我的代码不起作用。 我假设某些东西永远被封锁,但它没有多大意义。 任何人都可以解释我的代码如何工作,以及一个可能的解决方案,而无需更改为Task.Delay(只是这样我可以得到另一个视角,如何工作)?
Task.Delay
与使用Thread.Sleep
任务不同。 Task.Delay
内部使用Timer
,因此它不会阻塞任何线程,但是使用Thread.Sleep
启动一个新的任务会阻塞该线程(通常是Threadpool线程)。
在您的示例中,您从未启动过Task
。 使用构造函数创建Task
将返回需要通过调用Start
方法启动的Unstarted
任务。 否则它永远不会完成(因为你从未开始它)。
但是不鼓励调用Task.Start
,如果你想浪费一个 ,你可以调用Task.Factory.StartNew(()=> Thread.Sleep(1000))
或Task.Run(()=> Thread.Sleep(1000))
资源 。
此外,请注意StartNew是危险的 ,除了有令人信服的理由之外,你应该更喜欢Task.Run
不是StartNew
。
new Task(()=>Thread.Sleep(1000))
创建一个Task,但不启动它。
您可以使用Task.Run(() => Thread.Sleep(1000))
或Task.Factory.StartNew(() => Thread.Sleep(1000))
来创建和启动任务。
要回答问题标题 – Task.Delay
是可取消的!
考虑使用TaskCompletionSource
的流行实现。
static Task Delay(int delayTime, System.Threading.CancellationToken token) { TaskCompletionSource
你不能用Thread.Sleep
做到这一点。 你可以使用一个很大的旧循环,但它只是在上面的代码中模拟底层的Timer
。