実行時間の長いメソッドがあり、それにタイムアウトを追加したいと思います。それを行うことは可能ですか?何かのようなもの:
AbortWaitSeconds(20)
{
this.LongRunningMethod();
}
20秒に達すると、メソッドは中止されます。メソッドにはループがなく、そのメソッドに対する制御/コードもありません。
これを試して
class Program
{
static void Main(string[] args)
{
if (RunWithTimeout(LongRunningOperation, TimeSpan.FromMilliseconds(3000)))
{
Console.WriteLine("Worker thread finished.");
}
else
{
Console.WriteLine("Worker thread was aborted.");
}
}
static bool RunWithTimeout(ThreadStart threadStart, TimeSpan timeout)
{
Thread workerThread = new Thread(threadStart);
workerThread.Start();
bool finished = workerThread.Join(timeout);
if (!finished)
workerThread.Abort();
return finished;
}
static void LongRunningOperation()
{
Thread.Sleep(5000);
}
}
あなたはそれを見ることができます
一般的な解決策については、この質問に対する私の回答を参照してください。
そのコードを制御することはできないので、正しいアプローチは、WaitHandlesとThreadPoolを使用してそのコードを実行することだと思います。
WaitHandle waitHandle = new AutoResetEvent(false);
ThreadPool.QueueUserWorkItem(new WaitCallback(<long running task delegate>), waitHandle);
WaitHandle.WaitAll(new[]{ waitHandle }, <timeout>);
ここでは、WaitHandleがどのように機能するかについての詳細を見つけることができます。
バックグラウンドスレッドで計算を行い、スレッドが終了するまで待ちます。計算を中止するには、を使用します。これにより、計算スレッドにThread.Abort()
がスローされます。ThreadAbortException
チェックを導入して終了するコードポイントがある場合にのみ、同じスレッドから長時間実行されているプロセスを中止できます。これは、スレッドがビジーであるため、チェックを処理してそれ自体を中止できないためです。したがって、「LongRunningMethod」への呼び出しが1つしかない例では、同じスレッドから中止できませんでした。その方向性を得るためには、より多くのコードを表示する必要があります。
原則として、長時間実行されるタスクは、中止できるように、さまざまなスレッドに送信するのが最適です(たとえば、BackgroundWorkerまたは新しいスレッドを介して)。
これを行う簡単な方法は次のとおりです。
private void StartThread()
{
Thread t = new Thread(LongRunningMethod);
t.Start();
if (!t.Join(10000)) // give the operation 10s to complete
{
// the thread did not complete on its own, so we will abort it now
t.Abort();
}
}
private void LongRunningMethod()
{
// do something that'll take awhile
}