2 cqtrq cqtrq 于 2016.03.16 16:11 提问

await Task.Delay(1000)和Task.Delay(1000).Wait()

经测试对比,两种延时策略有以下区别:
若采用await Task.Delay(1000);的延时策略,Task.Status第一遍循环中为Running,以后的循环中全部为RanToCompletion,退出循环后仍然为RanToCompletion;
若采用Task.Delay(1000).Wait();的策略,循环中Task.Status一直为Running,退出循环即为RanToCompletion。

请问:为什么是这样?从测试结果看采用Task.Delay(1000).Wait()似乎更合理,但大家在实际应用中似乎更多使用await Task.Delay(1000),包括MSDN上的例子。

CancellationTokenSource cts = new CancellationTokenSource();
Task taskT;

private void button1_Click(object sender, EventArgs e)
        {
            taskT = Task.Factory.StartNew(() => t(cts.Token), cts.Token);
        }

 private async Task t(CancellationToken token)
        {
            Console.WriteLine("taskT.Status2:{0}", taskT.Status);
            while (true)
            {
                Console.WriteLine();
                if (token.IsCancellationRequested)
                {
                    Console.WriteLine("线程被终止!");
                    break;
                }
                Console.WriteLine(DateTime.Now.ToString());

                Console.WriteLine("taskT.Status3:{0}", taskT.Status);
                //await Task.Delay(3000);
                Task.Delay(3000).Wait();
                //taskT.Wait(3000);

                Console.WriteLine("taskT.Status4:{0}", taskT.Status);
            }
            Console.WriteLine("taskT.Status5:{0}", taskT.Status);
        }

3个回答

cqtrq
cqtrq   2016.03.19 08:33
已采纳

经测试对比,问题出在Task.Delay语句,修改为:Thread.Sleep就一切OK了,不需要await修饰或.wait()。这样,循环中的Task.Status一直为Running,退出循环即为RanToCompletion。

caozhy
caozhy   Ds   Rxr 2016.03.16 18:32
cqtrq
cqtrq 看了这个链接,仍然没搞明白原因。既然使用了token,为什么还是这样?
2 年多之前 回复
cqtrq
cqtrq   2016.03.16 20:16

这样的token,和普通的if条件+break语句有啥区别?用得着定义CancellationTokenSource和CancellationToken吗?这其中一定有蹊跷!
使用token,就必须要能真实反映Task.Status的各种状态,否则就没意义了。

Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐
轻度解析异步~Task.Delay
1.暂停一段时间public static Task ShortDelay(TimeSpan delay) { await Task.Delay(delay); Console.WriteLine(string.Format("延迟{0}", delay)); }解析: 异步编程使用async与await关键字,搭配返回Task或其泛型 async的存在是为了代码中await的生效
Thread.Sleep(1000) 、Task.Delay(1000).Wait() 区别
We can use both Thread.Sleep() and Task.Delay() to suspend the execution of a program for some given time. But are we actually suspending the execution? What is the difference between these two? How
【C#】51. Await 处理并行任务(WhenAll)以及Task.Delay()
这篇文章主要说明两个问题:1、await如何替代ContinueWith来处理WhenAll之类的并行多任务;2、Task.Delay()的原理。 async static Task GetInfoAsync(string name, int seconds) { await Task.Delay(TimeSpan.FromSeconds(seconds)); //await Task.Run(
taskDelay()滥用的结果~
STATUS netDevInit(void) { char opt = 0; int optval = 0; int tempAddrLen = 0; struct in_addr ifAddr;//--- 主网卡(fei0)初始化 if (ipAttach(0, "fei") == ERROR)... if (ifAddrSet("fei0", LOCA
异步编程中的最佳做法(Async/Await)
异步编程中的最佳做法 Stephen Cleary   近日来,涌现了许多关于 Microsoft .NET Framework 4.5 中新增了对 async 和 await 支持的信息。 本文旨在作为学习异步编程的“第二步”;我假设您已阅读过有关这一方面的至少一篇介绍性文章。 本文不提供任何新内容,Stack Overflow、MSDN 论坛和 async/awa
UWP中如何利用异步编程跳出死循环
UWP中,我设置了两个按钮,单击第一个按钮进行一个循环,单击第二个按钮停止这个循环,但是不管怎么处理按下第一个按钮以后都成了一个死循环,程序呈现卡死状态。这就让我想到必须要用异步编程来解决这个问题,网上UWP的教程什么的实在太少了,在MSDN里面研究了一天到底怎么写异步,终于是让我给解决了! 接下来就简单讲一下怎么进行异步编程跳出这个死循环: private async void FirstB
C# 延时程序 delay
C# 延时 函数 方法, 事件 阻塞 系统 定时器 ,AutoResetEven
wait(1000)与sleep(1000)的区别
sleep和wait的区别: 1、sleep是Thread的静态方法,wait是Object的方法,任何对象实例都能调用。 2、sleep不会释放锁,它也不需要占用锁。wait会释放锁,但调用它的前提是当前线程占有锁(即代码要在synchronized中)。 3、它们都可以被interrupted方法中断。 具体来说: Thread.Sleep(1000) 意思是在未来的1000毫秒内本
延时函数delay与sleep有什么区别呢?
在VC中使用带上头文件 #include <windows.h> 注意: 在VC中Sleep中的第一个英文字符为大写的"S" 在标准C中是sleep, 不要大写.. 下面使用大写的来说明,, 具体用什么看你用什么编译器. 简单的说VC用Sleep, 别的一律使用sleep. Sleep函数的一般形式: Sleep(unisgned long); 其中,Sleep()里面的单位,是以毫秒为单位,所以如果想让函数滞留1秒的话,应该是Sleep(1000);
关于Task的一点思考和建议
建议异步返回Task或Task 当在.NET Core中写爬虫用到异步去下载资源后接下来进行处理,对于处理完成结果我返回void,想到这里不仅仅一愣,这么到底行不行,翻一翻写的第一篇博客,只是提醒了我下不要用void,至于为何不用也没去探讨,接下来我们来探讨下返回值为Task和void,至于Task这个和Task类似。我们直接看代码,首先演示void,如下: pri