web-dev-qa-db-ja.com

ミリ秒数を設定するためのメソッドの一時停止

メソッドで一種の「タイムアウト」を行うか、メソッドで10秒間(10000ミリ秒)一時停止する必要がありますが、マルチスレッドを使用していないため、以下が機能するかどうかわかりません。

Thread.Sleep(10000);

私はその現在のコードを使用しようとしますが、特に上記のコードが正しく機能しない場合は、誰かがこれを行うための最良かつ正しい方法を説明できれば幸いです。ありがとう!

[〜#〜] update [〜#〜]:このプログラムは実際には問題の関数で1つのサーバーに対して多数のHTTPWebRequestを実行しているコンソールアプリケーションなので、指定した量だけ遅延させたいミリ秒の。したがって、コールバックは必要ありません。必要なのは「無条件の一時停止」だけです。基本的には、全体が10秒間停止してから続行します。 C#がこれをまだスレッドと見なしていて、Thread.Sleep(...)が機能することをうれしく思います。みんなありがとう!

17
Maxim Zaslavsky

multi-threadingがなくても、スレッド内で実行している場合、すべてのコードがスレッド内で実行されます。

Thread.Sleepを呼び出すと、実際に現在のスレッドが一時停止します。それを本当に無条件に10秒間一時停止させますか、それとも何か他のことが起こったときに「起こされる」ようにしたいですか?実際に1つのスレッドのみを使用している場合は、Sleepを呼び出すのが最善の方法ですが、状況によって異なります。

特に、GUIアプリを作成している場合、UIスレッドからThread.Sleepを使用したいしないでくださいそうしないと、アプリ全体が10秒間応答しなくなります。

アプリケーションについてより多くの情報を提供できれば、それは私たちがより良いアドバイスをするのに役立ちます。

16
Jon Skeet

これにより、実行中のスレッド/メソッドが10秒間一時停止します。特定の問題が発生していますか?

UIスレッドをSleepしないでください。代わりにコールバックを実行することをお勧めします。

スレッドをブロックする方法が他にもあることにも注意してください(2秒後に問題がなければ、より簡単なアクセスでスレッドを再開できます)。 Monitor.Wait(obj, 10000)など(それをウェイクアップする必要がある場合は、別のスレッドにPulseを許可します)

static void Main() {
    object lockObj = new object();
    lock (lockObj) {
        new Thread(GetInput).Start(lockObj);
        Monitor.Wait(lockObj, 10000);
    }
    Console.WriteLine("Main exiting");
}
static void GetInput(object state) {
    Console.WriteLine("press return...");
    string s = Console.ReadLine();
    lock (state) {
        Monitor.Pulse(state);
    }
    Console.WriteLine("GetInput exiting");
}

Thread.Interruptでもこれを行うことができますが、IMOは面倒です。

3
Marc Gravell

これは、目的のミリ秒の間一時停止し、CPUリソースを消費しない一時停止クラスです。

public class PauseClass
{
    //(C) Michael Roberg
    //Please feel free to distribute this class but include my credentials.

    System.Timers.Timer pauseTimer = null;

    public void BreakPause()
    {
        if (pauseTimer != null)
        {
            pauseTimer.Stop();
            pauseTimer.Enabled = false;
        }    
    }

    public bool Pause(int miliseconds)
    {
        ThreadPriority CurrentPriority = Thread.CurrentThread.Priority;

        if (miliseconds > 0)
        {
            Thread.CurrentThread.Priority = ThreadPriority.Lowest;

            pauseTimer = new System.Timers.Timer();
            pauseTimer.Elapsed += new ElapsedEventHandler(pauseTimer_Elapsed);

            pauseTimer.Interval = miliseconds;
            pauseTimer.Enabled = true;

            while (pauseTimer.Enabled)
            {
                Thread.Sleep(10);
                Application.DoEvents();
                //pausThread.Sleep(1);
            }

            pauseTimer.Elapsed -= new ElapsedEventHandler(pauseTimer_Elapsed);
        }

        Thread.CurrentThread.Priority = CurrentPriority;

        return true;
    }

    private void pauseTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        pauseTimer.Enabled = false;
    }
}
3
MarzSocks

別のスレッドを使用してそれを行うことができます:

   ThreadPool.QueueUserWorkItem(
       delegate(object state)
       {
           Thread.Sleep(1000);
           Console.WriteLine("done");
       });

ただし、これがWindowsフォームアプリの場合は、Guiスレッドから遅延後にコードを呼び出す必要があります(この記事の例: 更新方法C#の別のスレッドからのGUI? )。

[編集]更新を見たところです。それがコンソールアプリの場合、これは機能します。ただし、これまでに複数のスレッドを使用したことがない場合は、このコードが別のスレッドで実行されることに注意する必要があります。つまり、スレッド同期の問題に注意する必要があります。

バックグラウンドワーカーが必要ない場合は、「シンプルに保つ」に固執します。

3
Groo

Thread.Sleepは問題なく、AFAIKは適切な方法です。マルチスレッド化されていない場合でも、常に少なくとも1つのスレッドがあり、それをスリープ状態に送信すると、スリープ状態になります。

別の(bad)方法 はスピンロックです 、次のようなもの:

// Do never ever use this
private void DoNothing(){ }

private void KillCPU()
{
    DateTime target = DateTime.Now.AddSeconds(10);
    while(DateTime.Now < target) DoNothing();
    DoStuffAfterWaiting10Seconds();
}

これは残念ながらまだ人々に使用されており、プログラムが10秒間停止しますが、CPU使用率は100%で実行されます(マルチコアシステムでは1コアです)。

2
Michael Stum

はい、それはうまくいきます。

Threadクラスの一部のメソッドを利用するために、複数のスレッドを用意する必要はありません。常に少なくとも1つのスレッドがあります。

1
Guffa

タイムアウトの場合は、静的な揮発性ブールisRunningクラスフィールドが必要です。新しいスレッドが開始すると、isRunningがtrueになり、最後にfalseになる必要があります。

メインスレッドには、定義したタイムアウト中にisRunningをループするメソッドが必要です。タイムアウトが終了したら、ロジックを実装する必要があります。ただし、アボートスレッドメソッドは使用しないでください。

一時停止...簡単な解決策はありません。スレッド内で何をしているのかによります。ただし、 Monitor.Wait を確認できます。

0
Ricardo