主线程启动异步任务,执行它的主要任务,并在最后检查异步任务的结果.
异步线程提取数据并计算对主线程不完整的字段.但是,如果计算能够在不减慢主线程的情况下完成,那么这些数据会很好(并且应该包括在内).
I’d like to setup the async task to run at minimum for 2 seconds,but
to take all the time available between start and end of the main task.
It’s a ‘lazy timeout’ in that it only timeouts if exceeded the 2
second runtime and the result is actually being requested. (The async
task should take the greater of 2 seconds,or the total runtime of the
main task)
编辑(试图澄清要求):如果异步任务有机会运行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; } }
有没有人比这个包装有更好的解决方案?
解决方法
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后过渡到取消.如果计算先前完成,它将收到该结果.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。