У меня есть асинхронная операция, зависящая от другого сервера, которая занимает в основном случайное количество времени.Во время выполнения асинхронной операции в «главном потоке» также происходит обработка, для завершения которой также требуется произвольное время.
Основной поток запускает асинхронную задачу, выполняет свою основную задачу и проверяет еедля результата асинхронной задачи в конце.
Асинхронный поток извлекает данные и вычисляет поля, которые не являются критическими для завершения основного потока.Однако эти данные было бы неплохо иметь (и должны быть включены), если вычисление может быть завершено без замедления основного потока.
Я бы хотел настроитьасинхронная задача выполняется минимум 2 секунды, но занимает все доступное время между началом и концом основной задачи.Это «ленивый тайм-аут» в том смысле, что он только тайм-ауты, если превышено 2-секундное время выполнения, и результат фактически запрашивается.(Асинхронная задача должна занимать более 2 секунд или общее время выполнения основной задачи)
РЕДАКТИРОВАТЬ (пытаясь уточнить требования): Если асинхронная задача имеетбыл шанс запустить в течение 2 секунд, он не должен блокировать основной поток вообще.Основной поток должен разрешить выполнение асинхронной задачи не менее 2 секунд.Кроме того, если основному потоку требуется более 2 секунд, асинхронная задача должна выполняться до тех пор, пока основной поток.
Я разработал оболочку, которая работает, однако я бы предпочелрешение, которое на самом деле имеет тип задачи.См. Мое решение для оболочки ниже.
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;
}
}
У кого-нибудь есть лучшее решение, чем эта оболочка?