2016-09-23 84 views
0

我有調用外部lib同步操作的代碼,這可能需要很長時間才能完成。我不能重寫這個庫,並且沒有一種方法來停止操作。有什麼解決方案可以在超時後停止這項任務嗎?強制取消異步包裝同步任務

我已經試過這段代碼,但它不起作用,因爲我預期。等待直到計算未完成。

我該如何解決這個問題?

private static async Task<ResultData> GetResultAsync(string fileName) 
    { 
     var timeoutSource = new CancellationTokenSource(new TimeSpan(0, 5, 0)); 
     try 
     { 
      return await Task.Run(() => 
      { 
       var result = ExternLib.Calculate(fileName); 
       if (result == null) 
       { 
        throw new CalculationException(fileName); 
       } 
       return result; 
      }, 
       timeoutSource.Token 
      ).ConfigureAwait(false); 
     } 
     catch (AggregateException e) 
     { 
      SomeCode(e); 
     } 
     catch (OperationCanceledException e) 
     { 
      SomeCode2(e); 
     } 
     catch (Exception e) 
     { 
      SomeCode3(e); 
     } 
     return await Task.FromResult<ResultData>(null).ConfigureAwait(false); 
    } 
+0

'return await Task.FromResult (null).ConfigureAwait(false);' - >'return null;' –

+0

@StephenCleary我知道這一點。只有一個例外被捕獲時纔是這種情況。在正常情況下,try塊內的返回值將返回正確的結果。 – Anton

回答

1

創建兩個任務,其中一個做的工作,和一個充當計時器:

var workTask = Task.Run(() => // etc); 
var timerTask = Task.Delay(TimeSpan.FromMinutes(10)); 

的等待要麼任務完成:

var completedTask = Task.WaitAny(new[] { workTask, timerTask }); 

然後,如果completedTask是計時器任務,那麼您的超時已到期,您可以採取適當的措施:是否可以停止長時間運行的任務取決於它的結構,但你確實知道你可以停止等待它。

+0

不錯的做法 - 只需要注意不要讓用戶甩掉幾百次的重試按鈕:) – plast1k

+0

謝謝你的解決方案。這不是銀彈,但它的工作原理)@ plast1k這種方法是由某種非用戶引起的事件調用的 – Anton