2016-09-23 87 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