Я хочу знать, как отменить Задачи. уже читал такие статьи: https://docs.microsoft.com/en-us/dotnet/standard/threading/cancellation-in-managed-threads?redirectedfrom=MSDN
Но я уже выполнил задачи и хочу знать, как сделать их отменяемыми.
Либо все сразу, а если это невозможно, то следует отменить одно задание, а затем он должен отменить следующее, пока все не будут устранены.
РЕДАКТИРОВАТЬ Правильно ли используется CancellationToken? Задачи продолжают выполняться, как я и хотел, но когда я нажимаю кнопку отмены, я получаю ошибку. Если я запускаю свою опубликованную версию, приложение просто закрывается:* введите описание изображения здесь
void btnPause_Click(object sender, EventArgs e)
{
cts.Cancel();
}
async void btnStart_Click(object sender, EventArgs e)
{
try
{
cts = new CancellationTokenSource();
var token = cts.Token;
var t1 = Task.Run(() => START(token));
await Task.WhenAny(new[] { t1 });
}
catch (OperationCanceledException)
{
// Handle canceled
}
catch (Exception)
{
// Handle other exceptions
}
}
///////////////////////////////////////////
async void START(CancellationToken token)
{
for (int i = 0; i < 1; i++)
{
token.ThrowIfCancellationRequested();
await Task.Delay(100, token);
try {
if ()
{
}
}catch { }
}
Thread.Sleep(2000);
var t2 = Task.Run(() => START2(token));
await Task.WhenAny(new[] { t2});
}
///////////////////////////////////////////////
async void START2(CancellationToken token)
{
for (int i = 0; i < 10; i++)
{
token.ThrowIfCancellationRequested();
await Task.Delay(100, token);
try {
if ()
{
}
}catch { }
}
Thread.Sleep(7000);
var t3 = Task.Run(() => MOVE(token));
await Task.WhenAny(new[] {t3});
}
//////////////////////////////////////////
async void MOVE(CancellationToken token)
{
for (int i = 0; i < 3; i++)
{
token.ThrowIfCancellationRequested();
await Task.Delay(100, token);
try {
if ()
{
}
}catch { }
}
var t4 = Task.Run(() => MOVE2(token));
await Task.WhenAny(new[] {t4 });
}
Я надеялся на конструкцию, которую смогу использовать в своих задачах. В статье я не понимаю, как завершить все задачи одной кнопкой, потому что я использую ожидающие задачи. А в статье такое ощущение, что все в одной основной и одна потом выходит на задачу "DoSomeWork".. А мне нужно на нескольких задачах одновременно и я не могу найти то что ищу или я Я просто слепой и не замечаю этого постоянно. :/? Я попробовал это, и я не могу использовать токен отмены cts.Cancel(); на моей кнопке «Стоп», потому что я думаю, что это не глобально?
Вы создаете один CancellationTokenSource
и передаете значение его параметра .Token
(который является CancellationToken
) всем своим задачам, где вы проверяете, было ли оно отменено, регулярно вызывая cancellationToken.ThrowIfCancellationRequested()
, и перехватываете полученное OperationCanceledException
, где это уместно. Когда ваша кнопка нажата, вы звоните cancellationTokenSource.Cancel()
Используйте CancellationTokenSource в несколько упрощенном примере:
CancellationTokenSource cts = new CancellationTokenSource();
async void Cancel_Click(object sender, EventArgs e)
{
cts.Cancel();
}
async void btnStart_Click(object sender, EventArgs e)
{
try{
cts = new CancellationTokenSource();
var token = cts.Token;
var t1 = Task.Run(() => Start(token));
var t2 = Task.Run(() => Start(token));
await Task.WhenAny(new []{t1, t2});
}
catch(OperationCancelledException){
// Handle canceled
}
catch(Exception){
// Handle other exceptions
}
}
void Start(CancellationToken token)
{
for (int i = 0; i < 100; i++)
{
token.ThrowIfCancellationRequested();
// Do work
Thread.Sleep(100);
}
}
При нажатии кнопки сначала создается новый CancelTokenSource, а затем запускаются две задачи в фоновых потоках, обе с использованием токена из вновь созданного источника токенов. Когда нажата кнопка cancelButton, токен будет переведен в состояние отмены, и в следующий раз, когда каждый фоновый поток вызовет ThrowIfCancellationRequested, они вызовут исключение. Это поместит задачу в отмененное состояние, и в ожидании этого будет вызвано OperationCancelledException, которое необходимо поймать. Обратите внимание, что при ожидании нескольких задач вы можете получить агрегатное исключение, который упаковывает несколько исключений и должен быть распакован.
Было бы лучше, если это возможно, использовать await Task.Delay(100, token)
, а не Thread.Sleep
, чтобы сон отменялся, как только токен отменяется. Тогда и Task.Run
не нужен.
Task.WhenAny
? Ты собирался написать Task.WhenAll
?
спасибо за вашу работу действительно хорошо и легко понять :) У меня есть один вопрос. все мои задачи запускаются с ожиданием, потому что есть асинхронность... как я могу запустить эту задачу с ожиданием? var t1 = await Task.Run(() => RESTART(токен)); это неправильно... и мои задачи начинаются после выполнения следующей задачи... как я могу решить это с помощью вашего кода? я не хочу запускать все задачи сразу или я что-то не так понял?
я отредактировал свой пост и преобразовал свои задачи в это. это верно? Задачи продолжают выполняться, как я и хотел, но когда я нажимаю кнопку отмены, я получаю ошибку. Если я запускаю свою опубликованную версию, приложение просто закрывается. если я отредактирую свой код, как ваш: var t1 = Task.Run(() => Start(token)); var t2 = Task.Run(() => Start(token)); затем он запускает две задачи одновременно
@steven у вас, вероятно, есть исключение, закрывающее ваше приложение, см. мою заметку об агрегатном исключении и проверьте средство просмотра событий Windows, почему ваше приложение было закрыто. Кроме того, я бы очень не рекомендовал использовать асинхронные функции таким образом. Не усложняйте задачу, выполняйте некоторую работу, связанную с вычислениями, в фоновом потоке и обрабатывайте результат в потоке пользовательского интерфейса.
Большое спасибо, мне потребовалось много времени, чтобы понять это, но я понял это сейчас. Именно так я себе это и представлял :)
В статье, на которую вы ссылаетесь, содержится много подробностей. Что из этого тебе не понятно? Нет смысла говорить то же самое, что и в статье...