6

スレッドを開始したときに、スレッドが (最大で) 存続する時間の値を設定する方法はありますか?

別の言い方をすれば、「疑似コード」を使用すると、次のようなものがあります。

Thread t = new Thread();
t.start();
t.abort_after_x_seconds(30);

スレッドが 30 秒以上存続すると、スレッドが中止されます。

編集:私はまだそれを機能させることができません.私が最初に持っていたものは:

while(true)
{
    if(...)
    {
        Thread t = new Thread(new ThreadStart(startMethod));
        t.start();
    }
    Thread.sleep(...);
}

問題は、スレッドがハングすることがあることです (私はスレッドが何をするかを実装していないので、正確な理由はわかりません (これは学校のプロジェクトであり、私たちは組織化に慣れていません))、それらのスレッドを強制終了したいと考えています。以下の例のように、Tasks と CancellationTokens を使用してみましたが、Task がハングすると、キャンセル要求が発生したかどうかを確認できません。

4

3 に答える 3

7
  1. Threadほとんどの場合、s を使用するべきではなく、Task代わりに s を使用してください。それらはより便利で効率的です。
  2. 何かを中止するのは安全ではありません。代わりに協調的なキャンセルを使用する必要があります。キャンセルをサポートするメソッドを呼び出す場合は、30 秒後にキャンセルされるキャンセル トークンを渡すだけです。

したがって、コードは次のようになります (.Net 4.5 を使用):

var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)));
var task = Task.Run(() => YourMethod(cts.Token), cts.Token);
于 2013-11-11T14:24:25.413 に答える
1

[編集: 私の応答は遅すぎました。ただし、これはサンプル コード用に残しておきます。]

この目的には、共同キャンセルを使用する必要があります。スレッド自体は、いつ終了すべきかを検出し、適切に応答する必要があります。

この目的で使用できる、CancellationTokenプロデュース フロム aと呼ばれるものがあります。CancellationTokenSource

CancellationTokenSourceタイムアウトを設定できるコンストラクターもあります。

その使用方法を示すサンプル コードを次に示します。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace Demo
{
    class Program
    {
        private void run()
        {
            using (var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)))
            {
                var task = Task.Run(() => exampleOne(tokenSource.Token));
                task.Wait();
            }

            using (var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)))
            {
                var task = Task.Run(() => exampleTwo(tokenSource.Token));
                task.Wait();
            }

            Console.WriteLine("Done.");
        }

        static void exampleZero()
        {
            Console.WriteLine("Starting exampleZero()");

            try
            {
                Thread.Sleep(10000); // Simulate work.
            }

            catch (OperationCanceledException)
            {
                Console.WriteLine("Operation cancelled.");
            }

            Console.WriteLine("Exiting exampleZero()");
        }

        static void exampleOne(CancellationToken cancellation)
        {
            Console.WriteLine("Starting exampleOne()");

            // Busy loop processing.

            while (!cancellation.IsCancellationRequested)
            {
                // Do some work.
            }

            Console.WriteLine("Exiting exampleOne()");
        }

        static void exampleTwo(CancellationToken cancellation)
        {
            Console.WriteLine("Starting exampleTwo()");

            while (!cancellation.WaitHandle.WaitOne(100)) // Wait 100ms between work.
            {
                // Do some work.
            }

            Console.WriteLine("Exiting exampleTwo()");
        }

        static void Main()
        {
            new Program().run();
        }
    }
}
于 2013-11-11T14:35:35.077 に答える
0

コメント者が言っているように、使用Abortは悪い習慣であり、すぐに中止される保証はありません。なぜスレッドを存続させたいのですか?割り当てられたタスクが完了すると、スレッドは解放されてプールに戻されます。次にスレッドでタスクが実行されると、別の新しいスレッドを作成するか、スレッドプールで使用可能なスレッドを再利用することにより、スレッドのプールから自動的に与えられます。

あなたのロジック/コードは悪いようで、何かをx秒間待ってから終了するのではなく、修正する必要があります。それ自体がノックオンの問題を引き起こします。

おそらく、代わりに 30 秒後に刻むことができるタイマーが必要な場合は、タイマーを無効にして手元のタスクを強制終了できます。

于 2013-11-11T14:22:21.407 に答える