web-dev-qa-db-ja.com

UIの実行をブロックせずに数秒待ちます

2つの命令の間に数秒待機したいのですが、実行はブロックされません。

たとえば、Thread.Sleep(2000)は実行をブロックするため、良くありません。

考え方は、メソッドを呼び出してから、X秒(たとえば20)待ってからイベントの受信を待機するというものです。 20秒の終わりに、20秒で何が起こったかに応じて何らかの操作を行う必要があります。

51
user3376691

あなたが望んでいるのはTask.Delayだと思います。これは、スリープのようにスレッドをブロックしません。つまり、非同期プログラミングモデルを使用して単一のスレッドを使用してこれを行うことができます。

async Task PutTaskDelay()
{
    await Task.Delay(5000);
} 

private async void btnTaskDelay_Click(object sender, EventArgs e)
{
    await PutTaskDelay();
    MessageBox.Show("I am back");
}
81
daniellepelley

私が使う:

private void WaitNSeconds(int segundos)
{
    if (segundos < 1) return;
    DateTime _desired = DateTime.Now.AddSeconds(segundos);
    while (DateTime.Now < _desired) {
         System.Windows.Forms.Application.DoEvents();
    }
}
23
Omar

これは、別のスレッドを使用する場合に適しています。

// Call some method
this.Method();

Task.Factory.StartNew(() =>
{
    Thread.Sleep(20000);

    // Do things here.
    // NOTE: You may need to invoke this to your main thread depending on what you're doing
});

上記のコードは.NET 4.0以降を想定しています。それ以外の場合は試してください。

ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
{
    Thread.Sleep(20000);

    // Do things here
}));
12
Matt

Omarのソリューションは、環境を.NET 4.5にアップグレードして非同期APIと待機APIにアクセスできない場合に適切です*。ただし、パフォーマンスの低下を回避するために行う必要がある重要な変更が1つあります。 CPUの過剰な使用を防ぐため、Application.DoEvents()の呼び出しの間にわずかな遅延を追加する必要があります。追加することにより

Thread.Sleep(1);

application.DoEvents()を呼び出す前に、このような遅延(1ミリ秒)を追加して、アプリケーションが利用可能なCPUサイクルをすべて使用しないようにすることができます。

private void WaitNSeconds(int seconds)
{
    if (seconds < 1) return;
    DateTime _desired = DateTime.Now.AddSeconds(seconds);
    while (DateTime.Now < _desired) {
         Thread.Sleep(1);
         System.Windows.Forms.Application.DoEvents();
    }
}

* Application.DoEvents()を使用する潜在的な落とし穴に関する詳細な説明については、 https://blog.codinghorror.com/is-doevents-evil/ を参照してください。

10
Nick Painter

あなたが物事をブロックしたくないし、マルチスレッドを使用したくない場合、ここにあなたのための解決策があります: https://msdn.Microsoft.com/en-us/library/system.timers.timer( v = vs.110).aspx

UIスレッドはブロックされず、タイマーは2秒待ってから何かを実行します。

上記のリンクからのコードは次のとおりです。

        // Create a timer with a two second interval.
    aTimer = new System.Timers.Timer(2000);
    // Hook up the Elapsed event for the timer. 
    aTimer.Elapsed += OnTimedEvent;
    aTimer.Enabled = true;

    Console.WriteLine("Press the Enter key to exit the program... ");
    Console.ReadLine();
    Console.WriteLine("Terminating the application...");
3
Daan

Thread.Sleep(2000)を使用することは本当にお勧めできません。いくつかの理由(いくつかは ここ と説明されています)が、何よりもデバッグ/テストに関しては役に立たないためです。

Thread.Sleep()の代わりに C#Timer を使用することをお勧めします。タイマーを使用すると、メソッドを頻繁に実行でき(必要な場合)、テストでの使用がはるかに簡単になります。ハイパーリンクのすぐ後ろにタイマーを使用する方法の非常に素晴らしい例があります-「2秒後に何が起こるか」というロジックをTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);メソッドに入力するだけです。

2
Matthias R.

System.Threading.Timerクラスを調べます。これがあなたが探しているものだと思います。

MSDNのコード例 は、このクラスがあなたがやろうとしていることと非常によく似ていることを示しているようです(一定時間後にステータスを確認してください)。

0
LB2