Чтобы отменить asynchronious операции по истечению определенного промежутка времени, пока еще в состоянии отменить операцию вручную использовать что-то вроде следующего
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
cts.CancelAfter(5000);
это приведет к отмене через пять секунд. Чтобы отменить операцию, все, что вам нужно сделать, это передать token
в ваш метод асинхронизации и использовать метод token.ThrowifCancellationRequested()
, где вы настроили обработчик событий где-нибудь, чтобы запустить cts.Cancel()
.
Так полный пример:
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
cts.CancelAfter(5000);
// Set up the event handler on some button.
if (cancelSource != null)
{
cancelHandler = delegate
{
Cancel(cts);
};
stopButton.Click -= cancelHandler;
stopButton.Click += cancelHandler;
}
// Now launch the method.
SomeMethodAsync(token);
Где stopButton
кнопка нажатия кнопки, чтобы отменить выполняемую задачу
private void Cancel(CancellationTokenSource cts)
{
cts.Cancel();
}
и метод определяется как
SomeMethodAsync(CancellationToken token)
{
Task t = Task.Factory.StartNew(() =>
{
msTimeout = 5000;
Pump(token);
}, token,
TaskCreationOptions.None,
TaskScheduler.Default);
}
сейчас , чтобы вы могли работать с потоком, но также разрешаете аннулировать пользователя, вам нужно будет написать 'p umping»метод
int msTimeout;
bool timeLimitReached = false;
private void Pump(CancellationToken token)
{
DateTime now = DateTime.Now;
System.Timer t = new System.Timer(100);
t.Elapsed -= t_Elapsed;
t.Elapsed += t_Elapsed;
t.Start();
while(!timeLimitReached)
{
Thread.Sleep(250);
token.ThrowIfCancellationRequested();
}
}
void t_Elapsed(object sender, ElapsedEventArgs e)
{
TimeSpan elapsed = DateTime.Now - this.readyUpInitialised;
if (elapsed > msTimeout)
{
timeLimitReached = true;
t.Stop();
t.Dispose();
}
}
Примечание, SomeAsyncMethod
возвратится прямо к абоненту. Чтобы заблокировать вызывающего абонента, вам придется переместить Task
в иерархию вызовов.
Я предпочитаю 'token.WaitHandle.WaitOne (TimeSpan.FromMilliseconds (5000)); 'но по сути это выглядит как самое чистое решение. – Onur
Onur, тогда вы могли бы сделать это просто так: token.WaitHandle.WaitOne (5000) ' – Nekromancer
Perfect Solution. Спасибо –