Сообщение Re[3]: Почему не отменяется задача? от 15.03.2021 21:27
Изменено 15.03.2021 22:13 Mystic Artifact
Re[3]: Почему не отменяется задача?
Здравствуйте, Passerby, Вы писали:
P>Здравствуйте, Mystic Artifact, Вы писали:
MA>> Потому что в цикле i всегда равно нолю?
P>Спасибо, исправил. Писал While, а для форума решил исправить на for, ошибку не заметил.
P>Вопрос остается. Почему нет отмены?
1. async методы всегда выполняются синхронно в месте вызова, до точки разрыва (await). Т.е. в таком состоянии твой код просто исполняется синхронно, и отмена не происходит просто потому, что, там некому его отменять. Поставь Console.WriteLine(i) в цикле, что бы видеть кол-во происходящих итераций.
2. В SignalNoServer v.Wait(ct) — бросает исключение при отмене (не уверен, что это предполагалось).
3. task.Dispose(); — нельзя делать без проверки состояния задачи, иначе получишь опять исключение.
В примере ниже в цикле запускается целая пачка SignalNoServer потому, что в твоём изначальном примере так и предполагалось видимо.
PS: Вместо таких городушек — можно было бы просто написать await.
PPS: Понятно, что мои исправления так же грязны как и исходный пример.
P>Здравствуйте, Mystic Artifact, Вы писали:
MA>> Потому что в цикле i всегда равно нолю?
P>Спасибо, исправил. Писал While, а для форума решил исправить на for, ошибку не заметил.
P>Вопрос остается. Почему нет отмены?
1. async методы всегда выполняются синхронно в месте вызова, до точки разрыва (await). Т.е. в таком состоянии твой код просто исполняется синхронно, и отмена не происходит просто потому, что, там некому его отменять. Поставь Console.WriteLine(i) в цикле, что бы видеть кол-во происходящих итераций.
2. В SignalNoServer v.Wait(ct) — бросает исключение при отмене (не уверен, что это предполагалось).
3. task.Dispose(); — нельзя делать без проверки состояния задачи, иначе получишь опять исключение.
В примере ниже в цикле запускается целая пачка SignalNoServer потому, что в твоём изначальном примере так и предполагалось видимо.
static async Task Main(string[] args)
{
CancellationTokenSource cts = new CancellationTokenSource();
Task task = null;
for (int i = 0; ; i++)
{
Console.WriteLine(i);
if (i != 0)
{
cts.Cancel();
Thread.Sleep(10);
// task.Dispose();
}
cts = new();
task = SignalNoServer(cts.Token);
}
}
static async Task SignalNoServer(CancellationToken ct)
{
await Task.Yield(); // безусловный разрыв
var v = Task.Delay(2000, ct);
try
{
v.Wait(ct);
}
catch (OperationCanceledException ocex)
{
}
if (!v.IsCanceled) Console.WriteLine("Обработка закончена " + DateTime.Now);
else Console.WriteLine("Cancelled: " + DateTime.Now);
//или другой вариант, в котором тоже нет отмены
//if (!ct.IsCancellationRequested) Console.WriteLine("Обработка закончена " + DateTime.Now);
v.Dispose();
}
PS: Вместо таких городушек — можно было бы просто написать await.
static async Task SignalNoServer(CancellationToken ct)
{
var v = Task.Delay(2000, ct);
try
{
await v;
}
catch (OperationCanceledException) { }
// if (ct.IsCancellationRequested) Console.WriteLine("Cancellation requested " + DateTime.Now);
if (!v.IsCanceled) Console.WriteLine("Обработка закончена " + DateTime.Now);
else Console.WriteLine("Cancelled: " + DateTime.Now);
//или другой вариант, в котором тоже нет отмены
//if (!ct.IsCancellationRequested) Console.WriteLine("Обработка закончена " + DateTime.Now);
v.Dispose();
}
PPS: Понятно, что мои исправления так же грязны как и исходный пример.
Re[3]: Почему не отменяется задача?
Здравствуйте, Passerby, Вы писали:
P>Здравствуйте, Mystic Artifact, Вы писали:
MA>> Потому что в цикле i всегда равно нолю?
P>Спасибо, исправил. Писал While, а для форума решил исправить на for, ошибку не заметил.
P>Вопрос остается. Почему нет отмены?
1. async методы всегда выполняются синхронно в месте вызова, до точки разрыва (await). Т.е. в таком состоянии твой код просто исполняется синхронно, и отмена не происходит просто потому, что, там некому его отменять. Поставь Console.WriteLine(i) в цикле, что бы видеть кол-во происходящих итераций.
2. В SignalNoServer v.Wait(ct) — бросает исключение при отмене (не уверен, что это предполагалось).
3. task.Dispose(); — нельзя делать без проверки состояния задачи, иначе получишь опять исключение.
В примере ниже в цикле запускается целая пачка SignalNoServer потому, что в твоём изначальном примере так и предполагалось видимо (но отличается от того что ты описывал словами).
PS: Вместо таких городушек — можно было бы просто написать await.
PPS: Понятно, что мои исправления так же грязны как и исходный пример.
P>Здравствуйте, Mystic Artifact, Вы писали:
MA>> Потому что в цикле i всегда равно нолю?
P>Спасибо, исправил. Писал While, а для форума решил исправить на for, ошибку не заметил.
P>Вопрос остается. Почему нет отмены?
1. async методы всегда выполняются синхронно в месте вызова, до точки разрыва (await). Т.е. в таком состоянии твой код просто исполняется синхронно, и отмена не происходит просто потому, что, там некому его отменять. Поставь Console.WriteLine(i) в цикле, что бы видеть кол-во происходящих итераций.
2. В SignalNoServer v.Wait(ct) — бросает исключение при отмене (не уверен, что это предполагалось).
3. task.Dispose(); — нельзя делать без проверки состояния задачи, иначе получишь опять исключение.
В примере ниже в цикле запускается целая пачка SignalNoServer потому, что в твоём изначальном примере так и предполагалось видимо (но отличается от того что ты описывал словами).
static async Task Main(string[] args)
{
CancellationTokenSource cts = new CancellationTokenSource();
Task task = null;
for (int i = 0; ; i++)
{
Console.WriteLine(i);
if (i != 0)
{
cts.Cancel();
Thread.Sleep(10);
// task.Dispose();
}
cts = new();
task = SignalNoServer(cts.Token);
}
}
static async Task SignalNoServer(CancellationToken ct)
{
await Task.Yield(); // безусловный разрыв
var v = Task.Delay(2000, ct);
try
{
v.Wait(ct);
}
catch (OperationCanceledException ocex)
{
}
if (!v.IsCanceled) Console.WriteLine("Обработка закончена " + DateTime.Now);
else Console.WriteLine("Cancelled: " + DateTime.Now);
//или другой вариант, в котором тоже нет отмены
//if (!ct.IsCancellationRequested) Console.WriteLine("Обработка закончена " + DateTime.Now);
v.Dispose();
}
PS: Вместо таких городушек — можно было бы просто написать await.
static async Task SignalNoServer(CancellationToken ct)
{
var v = Task.Delay(2000, ct);
try
{
await v;
}
catch (OperationCanceledException) { }
// if (ct.IsCancellationRequested) Console.WriteLine("Cancellation requested " + DateTime.Now);
if (!v.IsCanceled) Console.WriteLine("Обработка закончена " + DateTime.Now);
else Console.WriteLine("Cancelled: " + DateTime.Now);
//или другой вариант, в котором тоже нет отмены
//if (!ct.IsCancellationRequested) Console.WriteLine("Обработка закончена " + DateTime.Now);
v.Dispose();
}
PPS: Понятно, что мои исправления так же грязны как и исходный пример.