簡體   English   中英

c - 如何限制c中函數的執行時間?

[英]How to limit the execution time of a function in c sharp?

我有問題。 我正在編寫一個基准測試,我有一個功能,要么在 2 秒內完成,要么在 ~5 分鍾后完成(取決於輸入數據)。 如果執行時間超過 3 秒,我想停止該函數...

我該怎么做?

非常感謝!

嗯...,我有同樣的問題,在閱讀了這里的所有答案和引用的博客后,我解決了這個問題,

它讓我執行任何有時間限制的代碼塊,聲明包裝器方法

    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

最好的方法是您的函數可以經常檢查其執行時間,以決定停止它花費的時間太長。

如果不是這種情況,則在單獨的線程中運行該函數。 在您的主線程中啟動一個 3 秒計時器。 當計時器結束時,使用Thread.Abort() 終止單獨的線程(當然,除非函數已經結束)。 請參閱函數文檔中的示例代碼和使用注意事項。

在 C# 中停止函數的最好方法是函數中的return關鍵字,但是我怎么知道什么時候使用return關鍵字在中間停止函數,至少持續 3 秒后? System.DiagnosticsStopwatch類就是答案。 這個持續 2 秒到 5 分鍾(取決於輸入數據)的復雜函數在邏輯上使用了許多循環,甚至可能是遞歸,所以我的解決方案是,在該函數的第一行代碼中,創建一個Stopwatch的實例使用System.Diagnosticsnew關鍵字,通過調用 Stopwatch 類的Start()函數啟動它,並在每個循環和循環中,在開始處添加以下代碼:

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

(提示:您可以用手鍵入一次,然后按 Ctrl+C 復制,然后按 Ctrl+V 粘貼)。 如果該函數使用遞歸,為了節省內存,首先將 Stopwatch 設為全局實例而不是將其創建為本地實例,如果它在代碼開頭沒有運行,則啟動它。 您可以通過 Stopwatch 類的IsRunning了解這一點。 之后詢問經過的時間是否超過 3 秒,如果是( true )停止或重置秒表,並使用return關鍵字停止遞歸循環,非常好的函數啟動,如果你的函數持續很長時間,主要是因為遞歸不僅僅是循環。 這是。 如您所見,它非常簡單,我測試了這個解決方案,結果表明它有效! 自己試試吧!

您可以使用 fork/join 模式,在任務並行庫中這是通過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

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/

可以在單獨的線程中執行函數並使用Thread.Join(millisecondsTimeout)限制其執行:

using System.Threading;

Thread workThread = new Thread(DoFunc);
workThread.Start(param);

if (!workThread.Join(3000))
{
    // DoFunc() took longer than 3 seconds. Thread was aborted
}

private void DoFunc(object param)
{
    // do some long work
}

在線程中運行此函數並在 3 秒后終止它檢查此函數內的已用時間(我認為它在那里循環)。

由於 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 應用程序中做這樣的事情。

使用具有高性能計數器的操作系統回調,然后終止您的線程(如果存在)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM