我有一个异步操作取决于另一台服务器,它需要大部分随机的时间来完成。在异步操作正在运行的同时,“主线程”中还有一些处理正在进行,这也需要花费一定的时间来完成。异步延迟超时任务
主线程启动异步任务,执行它的主要任务,并在最后检查异步任务的结果。
异步线程拉取数据并计算对主线程完成不重要的字段。然而,如果计算能够完成而没有减慢的主线程,则该数据将会很好(并且应该被包括)。
我想设置异步任务,在最小运行2秒,但 采取一切开始和主要任务结束之间的可用时间。 这是一个'延迟超时',因为如果超过第二个运行时间并且实际上正在请求结果,则它仅超时。 (异步 任务应采取更大的2秒,或 主要任务的总运行时间)
EDIT(试图澄清的要求):如果异步任务有机会运行持续2秒钟,它根本不应该阻塞主线程。主线程必须允许异步任务至少运行2秒。此外,如果主线程需要超过2秒才能完成,则应允许异步任务与主线程一样运行。
我设计了一个可以工作的包装,但是我更喜欢一个实际上是Task类型的解决方案。看到我下面的包装解决方案。
public class LazyTimeoutTaskWrapper<tResult>
{
private int _timeout;
private DateTime _startTime;
private Task<tResult> _task;
private IEnumerable<Action> _timeoutActions;
public LazyTimeoutTaskWrapper(Task<tResult> theTask, int timeoutInMillis, System.DateTime whenStarted, IEnumerable<Action> onTimeouts)
{
this._task = theTask;
this._timeout = timeoutInMillis;
this._startTime = whenStarted;
this._timeoutActions = onTimeouts;
}
private void onTimeout()
{
foreach (var timeoutAction in _timeoutActions)
{
timeoutAction();
}
}
public tResult Result
{
get
{
var dif = this._timeout - (int)System.DateTime.Now.Subtract(this._startTime).TotalMilliseconds;
if (_task.IsCompleted ||
(dif > 0 && _task.Wait(dif)))
{
return _task.Result;
}
else
{
onTimeout();
throw new TimeoutException("Timeout Waiting For Task To Complete");
}
}
}
public LazyTimeoutTaskWrapper<tNewResult> ContinueWith<tNewResult>(Func<Task<tResult>, tNewResult> continuation, params Action[] onTimeouts)
{
var result = new LazyTimeoutTaskWrapper<tNewResult>(this._task.ContinueWith(continuation), this._timeout, this._startTime, this._timeoutActions.Concat(onTimeouts));
result._startTime = this._startTime;
return result;
}
}
有没有人比这个包装有更好的解决方案?
我很好奇你为什么想要后台任务花费比完成实际工作所需的时间更长的时间。 – 2012-02-04 17:12:19
这不应该花费比实际工作时间更长的时间。主线程只需要等待至多2秒,但如果主线程太忙而不能立即需要结果,则主线程要允许它运行超过2秒。如果主线程花费了2秒多的时间完成,主线程根本不想等待。 – hannasm 2012-02-04 17:28:54