2014-12-09 115 views
0

我想做某事像這樣的僞代碼:實現超時功能/塊

try for new Timespan(0,0,4) { 
    // maximum execution time of this block: 4 seconds 
    result = longRunningFunction(parameter); 
    doSthWithResult(result); 
    ... 
} catch(TimeOutException) { 
    Console.WriteLine("TimeOut occured"); 
} 

在C#中使用這樣的結構,如果沒有,我將如何實現,允許嘗試行爲執行一個函數/塊一段時間?

如果有幫助:我正在尋找ASP.NET WebAPI(儘管我也可以在WinForms應用程序中使用超時)。

+0

至少在winforms中,如果你想確保它只執行那個跨度,你就會遇到問題。問題是你需要多個線程,並且即使你告訴一個子線程關閉(殺死線程),也不能保證線程停止,直到應用程序本身停止(如果它的後臺線程可以變得更糟在申請結束後繼續存在)。 ASP.NET我不知道它是否有類似的問題。 Winforms可悲地有這個問題 – Thomas 2014-12-09 12:22:36

+1

取決於'longRunningFunction'的作用。您需要支持該方法中的取消。 – 2014-12-09 12:23:02

+0

http://stackoverflow.com/questions/4238345/asynchronously-wait-for-taskt-to-complete-with-timeout – 2014-12-09 12:23:52

回答

1

如果您希望longRunningFunction()本身停止,那麼您需要在該方法中實現邏輯來執行此操作。如何做到這一點取決於你沒有提供的方法的確切實現,所以根據你目前的問題,這是無法回答的。

但是,在很多情況下,簡單地放棄一個操作就足夠了,讓它自己運行到完成,而只是忽略結果。你可以稱之爲「繼續你的生活」。 :)

如果這裏的話,那麼這樣的事情應該爲你工作:

Task<T> resultTask = Task.Run(() => longRunningFunction(parameter)); 

// maximum execution time of this block: 4 seconds 
await Task.WhenAny(resultTask, Task.Delay(4000)); 

if (resultTask.IsCompleted) 
{ 
    doSthWithResult(resultTask.Result); 
} 
else 
{ 
    Console.WriteLine("TimeOut occurred"); 
} 

resultTask聲明與任何爲longRunningFunction()實際的返回類型爲更換T

請注意,上述情況是機會主義的,因爲即使長時間運行時間超過4秒並且Task.Delay(4000)贏得比賽,只要在您的代碼恢復到if (resultTask.IsCompleted檢查時完成,它就會仍將被視爲成功。如果您想要給它一個嚴格的截止點,如果Task.Delay(4000)先完成,即使操作完成,直到您真正檢查完第一個完成爲止,您可以通過查看首先完成哪個任務來完成該操作:

Task winner = await Task.WhenAny(resultTask, Task.Delay(4000)); 

if (resultTask == winner) 
{ 
    doSthWithResult(resultTask.Result); 
} 
else 
... 

最後:即使您確實需要longRunningFunction()停止,您可以使用上述技術,然後中斷else子句中的操作,在此子句中報告超時(通過任何適合您的情況的機制;再次,沒有實際的代碼,就不可能確切地說出它會是什麼)。