c# – 异步延迟超时任务
我有一个异步操作依赖于另一个服务器,它需要大部分随机的时间来完成.当异步操作正在运行时,“主线程”中也会进行处理,这也需要一段随机的时间来完成.
主线程启动异步任务,执行它的主要任务,并在最后检查异步任务的结果. 异步线程提取数据并计算对主线程不完整的字段.但是,如果计算能够在不减慢主线程的情况下完成,那么这些数据会很好(并且应该包括在内).
编辑(试图澄清要求):如果异步任务有机会运行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秒的任务,当它完成时,将你的计算标记为已取消.这可以节省您奇怪的“差异”时间计算.这是一些代码:
Task mainTask = ...; //represents your main "thread" Task computation = ...; //your main task Task timeout = TaskEx.Delay(2000); TaskCompletionSource tcs = new TCS(); TaskEx.WhenAll(timeout,mainTask).ContinueWith(() => tcs.TrySetCancelled()); computation.ContinueWith(() => tcs.TryCopyResultFrom(computation)); Task taskToWaitOn = tcs.Task; 这是伪代码.我只是想展示这项技术. TryCopyResultFrom用于通过调用TrySetResult()将calculate.Result复制到TaskCompletionSource tcs. 您的应用只使用taskToWaitOn.它将在2s后过渡到取消.如果计算先前完成,它将收到该结果. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |