web-dev-qa-db-ja.com

Cシャープで関数の実行時間を制限するにはどうすればよいですか?

問題があります。ベンチマークを作成していますが、2秒後または約5分後に実行される関数があります(入力データによって異なります)。そして、3秒以上実行されたらその機能を停止したい...

どうすればいいですか?

どうもありがとう!

15
Novellizator

最善の方法は、関数が実行時間をチェックして、停止するのに時間がかかりすぎると判断できるようにすることです。

そうでない場合は、別のスレッドで関数を実行してください。メインスレッドで3秒のタイマーを開始します。タイマーが経過したら、 Thread.Abort() を使用して別のスレッドを強制終了します(もちろん、関数が既に終了していない限り)。関数ドキュメントのサンプルコードと使用法の前置きを参照してください。

5
Serge Wautier

ええと...、私は同じ質問をしました、そしてここですべての答えと参照されたブログを読んだ後、私はこれに落ち着きました、

それは私に実行させますany時間制限のあるコードのブロック、ラッパーメソッドを宣言します

    public static bool ExecuteWithTimeLimit(TimeSpan timeSpan, Action codeBlock)
    {
        try
        {
            Task task = Task.Factory.StartNew(() => codeBlock());
            task.Wait(timeSpan);
            return task.IsCompleted;
        }
        catch (AggregateException ae)
        {
            throw ae.InnerExceptions[0];
        }   
    }

そして、それを使用して、このようなコードのブロックをラップします

    // code here

    bool Completed = ExecuteWithTimeLimit(TimeSpan.FromMilliseconds(1000), () =>
    {
         //
         // Write your time bounded code here
         // 
    });

    //More code
50
shankar_pratap

フォーク/結合パターンを使用できます。タスク並列ライブラリでは、これは Task.WaitAll() で実装されます。

using System.Threading.Tasks;

void CutoffAfterThreeSeconds() {

    // start function on seperate thread
    CancellationTokenSource cts = new CancellationTokenSource();
    Task loop = Task.Factory.StartNew(() => Loop(cts.Token));

    // wait for max 3 seconds
    if(Task.WaitAll(new Task[]{loop}, 3000)){
       // Loop finished withion 3 seconds
    } else {
       // it did not finish within 3 seconds
       cts.Cancel();           
    }        
}

// this one takes forever
void Loop() {
    while (!ct.IsCancellationRequested) {
        // your loop goes here
    }
    Console.WriteLine("Got Cancelled");
}

これにより、別のスレッドで他のタスクが開始され、完了するまで3000ミリ秒待機します。タイムアウト内に終了した場合はtrueを返し、そうでない場合はfalseを返すため、それを使用して次に何をするかを決定できます。

CancellationToken を使用して、結果が不要になったことを他のスレッドに通知して、正常に停止できるようにすることができます。

よろしくGert-Jan

3
gjvdkamp

C#で関数を途中で停止する最善の方法は、関数のreturnキーワードですが、少なくとも3秒続いた後、returnキーワードを使用して関数を途中で停止するタイミングを知るにはどうすればよいですか? _System.Diagnostics_のStopwatchクラスがその答えです。 (入力データに応じて)2秒から5分続くこの複雑な関数は、論理的に多くのループを使用し、場合によっては再帰を使用するため、その関数の最初の行のコードでStopwatchのインスタンスを作成することをお勧めします。 _System.Diagnostics_をnewキーワードとともに使用して、StopwatchクラスのStart()関数を呼び出して開始し、ループとループごとに、最初に次のコードを追加します。

_if (stopwatch.ElapsedMilliseconds >= 3000) { 
     stopwatch.Stop();
     // or 
     stopwatch.Reset(); 
     return;
 } 
_

(ヒント:手で1回入力し、Ctrl + Cをコピーしてから、Ctrl + Vで貼り付けることができます)。その関数が再帰を使用する場合、メモリを節約するために、最初にローカルインスタンスとして作成するのではなく、Stopwatchグローバルインスタンスを作成し、コードの先頭で実行されていない場合は開始します。 StopwatchクラスのIsRunningでそれを知ることができます。その後、経過時間が3秒を超えているかどうかを尋ね、はい(true)の場合、Stopwatchを停止またはリセットし、returnキーワードを使用して再帰ループを停止します。主に再帰が原因で関数が長時間続く場合は、関数を非常に適切に開始できます。ループ以上のもの。そういうことです。ご覧のとおり、これは非常に単純で、このソリューションをテストした結果、機能することがわかりました。自分で試してみてください!

3
user2133061
private static int LongRunningMethod()
{
    var r = new Random();

    var randomNumber = r.Next(1, 10);

    var delayInMilliseconds = randomNumber * 1000;

    Task.Delay(delayInMilliseconds).Wait();

    return randomNumber;
}

そして

var task = Task.Run(() =>
{
    return LongRunningMethod();
});

bool isCompletedSuccessfully = task.Wait(TimeSpan.FromMilliseconds(3000));

if (isCompletedSuccessfully)
{
    return task.Result;
}
else
{
    throw new TimeoutException("The function has taken longer than the maximum time allowed.");
}

それは私のために働きます!ソース: https://jeremylindsayni.wordpress.com/2016/05/28/how-to-set-a-maximum-time-to-allow-ac-function-to-run-for/ ==

2
Amino Trần

HiパフォーマンスカウンターでOSコールバックを使用し、存在する場合はスレッドを強制終了します

0
Artur Mustafin

この関数をスレッドで実行し、3秒後に強制終了しますまたはこの関数内の経過時間を確認します(ループがあると思います)。

0
x2.

C#および.netフレームワークはリアルタイム環境ではないため、3秒のカウントでさえ保証することはできません。あなたがそれに近づいたとしても、あなたはまだ電話しなければならないでしょう

メソッド内の他のすべての呼び出しの前にif(timeSpan > TimeSpan.FromSeconds(3) then goto endindentifier;

これはすべて間違っているので、いいえ、私が知っていることからそれを行うための信頼できる方法はありません。

あなたはこの解決策を試すことができますが

https://web.archive.org/web/20140222210133/http://kossovsky.net/index.php/2009/07/csharp-how-to-limit-method-execution-time

しかし、私は.netアプリケーションではそのようなことはしません。

0
Maxim V. Pavlov