[英]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.Diagnostics
的Stopwatch
類就是答案。 這個持續 2 秒到 5 分鍾(取決於輸入數據)的復雜函數在邏輯上使用了許多循環,甚至可能是遞歸,所以我的解決方案是,在該函數的第一行代碼中,創建一個Stopwatch
的實例使用System.Diagnostics
和new
關鍵字,通過調用 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;
在方法中的每個其他調用之前。
所有這些都是錯誤的,所以不,據我所知,沒有可靠的方法可以做到這一點。
雖然你可以試試這個解決方案
但我不會在 .net 應用程序中做這樣的事情。
使用具有高性能計數器的操作系統回調,然后終止您的線程(如果存在)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.