Когда Task.IsCancelled установлен как true?
Когда придет Task.IsCanceled = true;
Код:
var cts = new CancellationTokenSource();
string result = "";
cts.CancelAfter(10000);
try
{
Task t = Task.Run(() =>
{
using (var stream = new WebClient().OpenRead("http://www.rediffmail.com"))
{
result = "success!";
}
cts.Token.ThrowIfCancellationRequested();
}, cts.Token);
Stopwatch timer = new Stopwatch();
timer.Start();
while (timer.IsRunning)
{
if (timer.ElapsedMilliseconds <= 10000)
{
if (result != ""){
timer.Stop();
Console.WriteLine(result);
}
}
else
{
timer.Stop();
//cts.Cancel();
//cts.Token.ThrowIfCancellationRequested();
}
}
}
catch (OperationCanceledException)
{
Console.WriteLine(t.IsCanceled); // still its appear in false.
}
Мое требование - Задание не выполнено до 10 секунд, Необходимо отменить задание.
Поэтому я устанавливаю таймер и наблюдаю до заданных секунд. его не завершено означает отменить задачу и показать сообщение об ошибке.
2 ответа
Вы должны передать токен вашему методу. Следует проверить токен и уважать призыв к Cancel()
из CancellationTokenSource
,
Или ты делаешь это сам
Task t = Task.Factory.StartNew(() =>
{
myResult = method(); // Request processing in parallel
cts.Token.ThrowIfCancellationRequested(); // React on cancellation
}, cts.Token);
Полный пример таков:
async Task Main()
{
var cts = new CancellationTokenSource();
var ct = cts.Token;
cts.CancelAfter(500);
Task t = null;
try
{
t = Task.Run(() => { Thread.Sleep(1000); ct.ThrowIfCancellationRequested(); }, ct);
await t;
Console.WriteLine(t.IsCanceled);
}
catch (OperationCanceledException)
{
Console.WriteLine(t.IsCanceled);
}
}
Выход заключается в том, что OperationCanceledException
брошен и результат
Правда
если вы удалите ct.ThrowIfCancellationRequested();
часть это покажет
Ложь
Редактировать:
Теперь вы обновили вопрос, некоторые комментарии по этому поводу. Во-первых, вам больше не понадобится таймер, так как вы используете CancelAfter
метод. Во-вторых, вам нужно await
твое задание. Так что получается примерно так:
string result = "";
cts.CancelAfter(10000);
Task t = null;
try
{
t = Task.Run(() =>
{
using (var stream = new WebClient().OpenRead("http://www.rediffmail.com"))
{
cts.Token.ThrowIfCancellationRequested();
result = "success!";
}
}, cts.Token);
await t;
}
catch (OperationCanceledException)
{
Console.WriteLine(t.IsCanceled);
}
Это должно показать, что t.IsCanceled
является true
но, конечно, только когда вызов WebClient
занимает больше 10 секунд.
Из документации:
Задача будет выполнена в состоянии TaskStatus.Canceled при любом из следующих условий:
Его CancellationToken был помечен для отмены до начала выполнения задачи.
Задача подтвердила запрос на отмену в уже сигнализированном CancellationToken, выдав исключение OperationCanceledException, содержащее тот же CancellationToken.
Задача подтвердила запрос отмены в уже сигнализированном CancellationToken, вызвав метод ThrowIfCancellationRequested в CancellationToken.
Так что в основном вам нужно будет бросить OperationCanceledException
в вашей задаче, чтобы заставить государство, например, выполнив cts.Token.ThrowIfCancellationRequested()
только после того, как вы отмените это.
Но намерение этого механизма несколько наоборот. Вы отменяете источник, скажем, пока пользователь нажимает кнопку "Отмена" в вашей форме (вне вашей задачи), задача просто проверяет, была ли запрошена отмена в некотором сохранении, чтобы отменить пункты ее кода.