17

問題があります。私はベンチマークを書いており、2秒または〜5分後に(入力データに応じて)実行される関数があります。そして、3秒以上実行された場合、その機能を停止したいと思います...

どうすればいいですか?

どうもありがとう!

4

9 に答える 9

61

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

時間制限付きで任意のコード ブロックを実行できます。ラッパー メソッドを宣言します。

    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
于 2012-05-11T02:17:52.113 に答える
7

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

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

于 2011-09-14T09:07:41.883 に答える
4

C# で関数を途中で停止する最良の方法は、関数内のキーワードですが、少なくとも 3 秒続いた後、キーワードをreturn使用して関数を途中で停止するタイミングをどのように知ることができますか? returnからのStopwatchクラスSystem.Diagnosticsが答えです。(入力データに応じて) 2 秒から 5 分間続くこの複雑な関数は、多くのループを論理的に使用し、場合によっては再帰を使用するため、私の解決策は、その関数の最初の行コードで、Stopwatchusingのインスタンスを作成することですキーワードをSystem.Diagnostics使用して、Stopwatch クラスの関数を呼び出して開始し、for each ループとループの先頭に、次のコードを追加します。newStart()

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

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

于 2013-03-04T18:56:08.677 に答える
3

フォーク/結合パターンを使用できます。タスク並列ライブラリでは、これは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

于 2011-09-14T09:17:49.030 に答える
0

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 アプリケーションではそのようなことはしません。

于 2011-09-14T08:52:20.523 に答える
0

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

于 2011-09-14T09:03:12.353 に答える
0

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

于 2011-09-14T08:52:07.410 に答える