gpt4 book ai didi

c# - 异步延迟超时任务

转载 作者:行者123 更新时间:2023-11-30 12:33:31 26 4
gpt4 key购买 nike

我有一个依赖于另一台服务器的异步操作,它需要花费大部分随机时间才能完成。当异步操作正在运行时,“主线程”中也会进行处理,这也需要随机的时间才能完成。

主线程启动异步任务,执行它的主任务,最后检查异步任务的结果。

异步线程拉取数据并计算对主线程完成来说并不重要的字段。但是,如果计算能够在不减慢主线程的情况下完成,那么拥有(并且应该包括)这些数据会很好。

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;
}
}

有没有人有比这个包装器更好的解决方案?

最佳答案

我总是开始一个 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() 将 computation.Result 复制到 TaskCompletionSource tcs。

您的应用仅使用 taskToWaitOn。 2s 后会过渡到 cancelled。如果计算提前完成,它将收到计算结果。

关于c# - 异步延迟超时任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9142549/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com