【发布时间】:2012-02-04 16:49:52
【问题描述】:
我有一个依赖于另一台服务器的异步操作,这需要随机的时间来完成。在异步操作运行的同时,“主线程”中也在进行处理,这也需要随机的时间才能完成。
主线程启动异步任务,执行它的主任务,最后检查异步任务的结果。
异步线程提取数据并计算对主线程完成不重要的字段。但是,如果计算能够在不减慢主线程的情况下完成,那么拥有(并且应该包含)这些数据会很好。
我想将异步任务设置为至少运行 2 秒,但是 在主要任务的开始和结束之间占用所有可用的时间。 这是一个“延迟超时”,因为它只有在超过 2 时才会超时 第二个运行时,实际上正在请求结果。 (异步 任务应该花费 2 秒或总运行时间中的较大者 主要任务)
编辑(试图澄清要求):如果异步任务有机会运行 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;
}
}
有没有比这个包装器更好的解决方案?
【问题讨论】:
-
我很好奇为什么您希望后台任务花费的时间比执行实际工作的时间长。
-
这并不是说它应该比实际工作花费更长的时间。主线程最多只希望等待 2 秒,但如果主线程太忙而无法立即需要结果,则主线程希望允许它运行超过 2 秒。如果主线程完成时间超过 2 秒,则主线程根本不想等待。
标签: c# asynchronous multitasking