zoukankan      html  css  js  c++  java
  • Thread.Sleep vs Task.Delay

    一、概述

    Thread.Sleep()和Task.Delay()可以暂停程序(线程)的执行。但是实质是暂停执行吗?两者有什么区别?如何从休眠线程或已等待的任务中止?通过下面示例来进行说明,创建一个简单的winform程序,界面如下:
    有以下两种基本的辅助方法PutThreadSleep和PutTaskDelay,然后分别调用这两个方法:
         private void BtnThreadSleep_Click(object sender, EventArgs e)
            {
                PutThreadSleep();
                MessageBox.Show("I am back");
            }
    
            private async void BtnTaskDelay_Click(object sender, EventArgs e)
            {
                await PutTaskDelay();
                MessageBox.Show("I am back");
            }     
    
            void PutThreadSleep()
            {
                Thread.Sleep(5000);
            }
    
            async Task PutTaskDelay()
            {
                await Task.Delay(5000);
            }
    当我分别单击前两个按钮时,消息框将在5秒钟后显示。但是这两种实现之间存在重大差异。具体分析如下:
    • Thread.Sleep()

      这是挂起执行的经典方法。此方法将挂起当前线程,直到经过给定的时间。因为Thread.Sleep挂起了进行调用的线程,并且在按钮事件处理程序中调用Thread.Sleep(在UI线程中运行),因此UI处于休眠状态无响应,效果上来看就是无法拖动窗口了。当调用Thread.Sleep时,除了等待时间过去或通过重新启动应用程序外,您无法做任何其他操作来终止它。 

    • Task.Delay()

      Task.Delay的行为与Thread.Sleep的行为非常不同。基本上,Task.Delay将创建一个任务,该任务将在一段时间后完成。Task.Delay没有阻止调用线程因此UI将保持响应状态。幕后有一个计时器,直到指定的时间为止。由于计时器控制延迟,因此我们可以随时通过停止计时器来取消延迟。修改上面的PutTaskDelay方法,支持取消操作,如下所示:

    CancellationTokenSource tokenSource = new CancellationTokenSource();
    async Task PutTaskDelay()
    {
        try
        {
            await Task.Delay(5000, tokenSource.Token);
        }
        catch (TaskCanceledException ex)
        {
    
        }
        catch (Exception ex)
        {
    
        }
    }

    在对Task.Delay的调用中,我添加了一个取消令牌。当任务被取消时,它将抛出TaskCanceledException。这里仅仅捕捉到异常并加以抑制,并不显示任何有关此的消息。在“取消任务延迟”按钮单击事件处理程序中,通过使用取消令牌来指示要取消的任务:

    private void BtnCancelTaskDelay_Click(object sender, EventArgs e)
    {
        tokenSource.Cancel();
    }

    取消任务后,PutTaskDelay方法将立即返回,并且调用方将显示消息框。

    • 完整代码如下:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace WinFormsApp2
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            private void BtnThreadSleep_Click(object sender, EventArgs e)
            {
                PutThreadSleep();
                MessageBox.Show("I am back");
            }
    
            private async void BtnTaskDelay_Click(object sender, EventArgs e)
            {
                await PutTaskDelay();
                MessageBox.Show("I am back");
            }
            private void BtnCancelTaskDelay_Click(object sender, EventArgs e)
            {
                tokenSource.Cancel();
            }
    
            void PutThreadSleep()
            {
                Thread.Sleep(5000);
            }
    
            CancellationTokenSource tokenSource = new CancellationTokenSource();
            async Task PutTaskDelay()
            {
                try
                {
                    await Task.Delay(5000, tokenSource.Token);
                }
                catch (TaskCanceledException ex)
                {
    
                }
                catch (Exception ex)
                {
    
                }
            }
        }
    }

    二、总结

    • Thread.Sleep 是同步延迟,Task.Delay异步延迟
    • Thread.Sleep 会阻塞线程,Task.Delay不会
    • Thread.Sleep不能取消,Task.Delay可以
    • Task.Delay() 比 Thread.Sleep() 消耗更多的资源,但是Task.Delay()可用于为方法返回Task类型或者根据CancellationToken取消标记来动态取消等待
    • Task.Delay() 实质创建一个运行给定时间的任务, Thread.Sleep() 使当前线程休眠给定时间

    三、参考资料

    1、https://social.technet.microsoft.com/wiki/contents/articles/21177.visual-c-thread-sleep-vs-task-delay.aspx

  • 相关阅读:
    iscroll.js & flipsnap.js
    IE8’s Substr() Bug
    chrome扩展,如何阻止浏览自动关闭桌面通知.
    临时邮箱
    多个显示器, window.open的定位
    页面刷新
    PipelineDB Install and Test
    CitusDB UPSERT
    Kafka部署
    ambari-cassandra-service
  • 原文地址:https://www.cnblogs.com/qtiger/p/14816903.html
Copyright © 2011-2022 走看看