1. ホーム

C#のTask.Delay()とThread.Sleep()

2022-02-08 18:27:13
  1. Thread.Sleep()は同期遅延、Task.Delay()は非同期遅延です。
  2. Thread.Sleep()はスレッドをブロックし、Task.Delay()はブロックしない。
  3. Thread.Sleep()はキャンセルできませんが、Task.Delay()はキャンセル可能です。
  4. Task.Delay()は、基本的に与えられた時間だけ実行するタスクを作成し、Thread.Sleep()は現在のスレッドを与えられた時間だけスリープさせます。
  5. Task.Delay()をデコンパイルします。基本的にタイマーをタスクで包んだものです。
  6. Task.Delay()とThread.Sleep()の最大の違いは、Task.Delay()は非同期で実行することを目的としていることです。同期コードでTask.Delay()を使っても意味がありませんし、非同期コードでThread.Sleep()を使っても非常に悪いアイディアにしかなりません。Task.Delay()は通常、awaitキーワードで呼び出します。
  7. 私の理解では Task.Delay()、async/await、CancellationTokenSource を組み合わせて使用すると、非同期の遅延を制御することができます。

参考にしてください。

https://www.cnblogs.com/yy1234/p/8073732.html

https://blog.csdn.net/shu19880720/article/details/72901876

https://code.msdn.microsoft.com/ThreadSleep-vs-TaskDelay-766b46b7/view/Discussions#content

https://blog.csdn.net/wushang923/article/details/41015063

http://social.technet.microsoft.com/wiki/contents/articles/21177.visual-c-thread-sleep-vs-task-delay.aspx (コメント欄で物議をかもす)

https://oomake.com/question/5779232

https://walterlv.com/post/sleep-delay-zero-vs-yield.html

以下は、デバッグ時の私のコードです。

コード1

using System;
Threading;
Tasks;

namespace Delay_And_Sleep
Tasks; namespace Delay_And_Sleep
    class Program
    program
        static void Main(string[] args)
        StartNew(delegate) {
            Factory.StartNew(delegate
            StartNew(delegate) {
                Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ****** StartSleep()");
                for (int i = 1; i < 20; i++)
                {
                    Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff") + " ***Sleep*** " + i);
                    Thread.Sleep(100);
                }
                Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.ffff") + " ****** EndSleep()");
            });

            Task.Factory.StartNew(() =>
            {
                Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ====== Start Delay()");
                for (int i = 101; i < 120; i++)
                {
                    Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ===Delay=== " + i);
                    Task.Delay(100);//needs .net4.5 and above
                }
                Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ====== End Delay()");
            });

            //ToString("yyyy-MM-dd HH:mm:ss.ffff") + "press enter to close . . . ");
            Console.ReadLine();
        }
    }
}


実行結果を表示します。

コード2

using System;
Tasks;

namespace Delay_async_await
Tasks; namespace
    class Program
    Tasks; namespace Delay_async_await { class Program
        // This code implements "synchronous" Delay by async/awatit
        static void Main(string[] args)
        {
            Factory.StartNew(async () =>
            StartNew(async () => {
                Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ====== StartDelay()");
                for (int i = 101; i < 120; i++)
                {
                    Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ===Delay=== " + i);
                    await Task.Delay(100);//requires .net4.5 and above
                }
                Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + " ====== End Delay()");
            });

            //ToString("yyyy-MM-dd HH:mm:ss.ffff") + "press enter to close . . . ");
            Console.ReadLine();
        }
    }
}


実行結果。

コード3

using System;
Generic;
ComponentModel;
Data;
Data; using System;
Data; using System;
Text; using System;
Threading;
Tasks;
Tasks; using System;

namespace CancelDelay
Forms; namespace Cancel Delay
    public partial class Form1 : Form
    {
        CancellationTokenSource cts = new CancellationTokenSource();

        public Form1()
        {
            InitializeComponent();
        }

        void PutThreadSleep()
        {
            Thread.Sleep(5000);
        }

        async Task PutTaskDelay()
        {
            try
            {
                await Task.Delay(5000, cts.Token);// requires .
            Net4.5 support required }
            catch (TaskCanceledException ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void btnThreadSleep_Click(object sender, EventArgs e)
        {
            PutThreadSleep();
            MessageBox.Show("Sleep : I am back");
        }

        // use async/await to observe the effect; if not, just pop up the MessageBox
        private async void btnTaskDelay_Click(object sender, EventArgs e)
        {
            await PutTaskDelay();
            MessageBox.Show("Delay : I am back");
        }

        private void btnCancelTaskDelay_Click(object sender, EventArgs e)
        {
            cts.Cancel();
        }
    }
}



実行結果。