0

x秒ごとにいくつかの機能を開始したいと思います。しかし、関数を再度開始する前に、関数が完了するまで待ちたくありません。タイマーを 5 秒に設定して開始functionX()し、5 秒経過しても完了しないとします =>新しいスレッドで再度functionX()開始したいとします。functionX()また、関数のグループが同時に開始されることも望んでいます。

System.Threading.Timerそれが私が使用しなければならないと思った理由ですParallel。短い例を書いてみましょう。

class Program
    {
        private static System.Threading.Timer timer;
        private static int interval = 2000;

        static void Main(string[] args)
        {
            Console.WriteLine("go");
            Run();
            Console.WriteLine("end");
            Console.ReadKey();
        }

        private static void Run()
        {
            timer = new System.Threading.Timer(TimerCallback, null, 0, interval);
        }

        private static void TimerCallback(Object o) {
            Parallel.Invoke(() => FunctionA(), () => FunctionB(), () => FunctionC());
        }

        private static void FunctionA()
        {
            Console.WriteLine("A");
        }

        private static void FunctionB()
        {
            Console.WriteLine("B");
        }

        private static void FunctionC()
        {
            Console.WriteLine("C");
        }
    }

これでいいですか?助言がありますか?このコードが何らかの形で間違っている場合でも、出力について別の質問をしたいと思います。このコードを開始すると、次のような出力が得られます。

go
end
A
B
C
C
A
B
C
A
B
C
B
A

うーん。最初の出力goは問題ありませんがend、なぜ 2 番目の出力は , ではないABでしょCうか? そして、出力A、B、Cが最初の出力ランダムの後に何らかの形であるというのは正常ですか?

私が理解していない次の問題:行を削除すると、 Console.ReadKey();出力が表示されません。

        static void Main(string[] args)
        {
            Console.WriteLine("go");
            Run();
            Console.WriteLine("end");
        }

つまり、コンソールは起動していますが、数ミリ秒後に閉じられ、再び開かれません。しかし、A、B、C を何度も呼び出しているため、表示されるはずなので、新しいコンソールが何度も表示されるはずです。何か案は?ありがとうございました

4

2 に答える 2

2

メイン メソッドは、タイマーが作成された直後に戻ります。そのため、end非常に早く書かれています。コードの残りの部分はすべて、他のスレッドで実行されます。

タイマー メソッドは 3 つのジョブを .NETs Parallel 拡張機能に送信します。これらのジョブもバックグラウンド スレッドで実行されます。そのため、ABC のような順序付けされた出力が表示されず、ACB、BCA CBA などが表示されます。

したがって、メイン スレッド、タイマー バックグラウンド スレッド、および出力用の最大 3 つのワーカー スレッドがあります (CPU によって異なります)。

Console.ReadKey()、メール スレッドがキーボード入力を待機するようにします。この間、他のスレッドはジョブを処理できます。呼び出しを削除するReadKeyと、プログラムは書き込み後すぐに終了endし、他のスレッドが終了するのを待ちません。

コードを変更して、開始、終了、および ABC を記述するだけでなくThread.CurrentThread.ManagedThreadID、出力にも追加します。次に、どのスレッドがどのメソッドを実行しているかを確認できます。

于 2012-08-22T15:33:47.690 に答える
1

並列 (および他の同様のフレームワーク) は、開始されたタスク (スレッド) の実行順序を保証しません。実行順序が「A、B、C」であることを保証したい場合は、それらを関数に入れてスレッドで実行できます。

一方、''Main'' を終了すると、実行中のスレッドが中断されます。通常のサービスは、終了条件 (ユーザーが ESC を押す、信号を受信するなど) に達するまで無限にループする必要があります。

スレッドは単一のアプリケーション内で実行されているため、出力用に新しいコンソール ウィンドウを開くことはありません。

于 2012-08-22T15:36:19.247 に答える