Страницы

Поиск по вопросам

пятница, 29 марта 2019 г.

Остановка работы потока по нажатию кнопки

Я создал приложение для перепрошивки устройства по интерфейсу UART
Хочу добавить необязательное, но желаемое взаимодействие с программой: Остановка работы потока по нажатию на кнопку "Остановить выполнение". Программа работает следующим образом:
private void Execute_Commands_Button_Click(object sender, EventArgs e) // Нажатие на кнопку "Выполнить команды" { // Очистить данные Clear_Data(); // Если нет ошибок в полях if (Check_All_Fields()) { // Если есть соединение с портом if (Check_Port()) { // Если параметры работы с портом установлены успешно if (Set_Port_Settings()) { // Обновить данные Hex- файла Refresh_Hex_File_Data(); // Если устройство не синхронизировано if (!Is_Synchronised) { // Поток для синхронизации Thread Sync_Thread; // Поток для синхронизации Sync_Thread = new Thread(delegate() { // Выключить элементы управления Set_Enable(false); // Попытаться синхронизировать Try_To_Synchronise_Device(Convert.ToInt32( This_Common.Read_From_Registry(This_Common.Key_Sync_Attempts))); // Включить элементы управления Set_Enable(true); }); // Записываем поток как текущий Active_Thread = Sync_Thread; // Запуск потока Sync_Thread.Start(); // Ожидание завершения работы потока Sync_Thread.Join(); } // Если устройство синхронизировано if (Is_Synchronised) { // Обновить список команд Refresh_Commands(); // Попытаться послать команды на порт Try_To_Send_Commands(); } // Если устройство не синхронизировано else { // Вывести ошибку This_Common.Show_Error_Message("Не удалось синхронизироваться с устройством!"); } // Закрыть порт Selected_Port.Close(); } } } }
В функции void Set_Enable(bool) Все элементы управления становятся неактивными и включается только кнопка "Остановить выполнение". при нажатии на эту кнопку активный поток закрывается: Active_Thread.Abort()
Проблема заключается в следующем: после ожидания выполнения группы методов в отдельном потоке я теряю возможность обрабатывать нажатия на кнопку "Остановить выполнение". Как это можно исправить?
Вариант с Task не сработал. Код следующий:
// Обработчик запроса отмены задачи CancellationTokenSource Source = new CancellationTokenSource(); // Переменная отключения выполнения задачи CancellationToken Cancel_Token; // Задача "Синхронизировать" Task Sync_Task; // Задать задачу Sync_Task = new Task(delegate() { // Попытаться синхронизироваться Try_To_Synchronise_Device(Convert.ToInt32(This_Common.Read_From_Registry(This_Common.Key_Sync_Attempts))); }, Cancel_Token); // Запуск задачи Sync_Task.Start(); // Ожидаем выполнение задачи Source.Wait();
При клике на кнопку "Остановить выполнение": Source.Cancel();


Ответ

Я тоже наклепал пример попроще.

public partial class Form1 : Form { public Form1() { InitializeComponent(); }
//источник токена отмены CancellationTokenSource _tokenSource;
//Запуск private async void _buttonStart_Click(object sender, EventArgs e) { //через него будем оповещать о ходе выполнения задачи Progress progess = new Progress(text => this._labelOutput.Text = text);
//готовим токен отмены _tokenSource = new CancellationTokenSource(); CancellationToken cancelToken = _tokenSource.Token;
//запускаем долгую задачу try { this._labelOutput.Text = "Начинаем..."; //обратите внимание на передачу токена отмены, и экземпл. прогресса this._labelOutput.Text = await Task.Run(() => DoSomething(cancelToken, progess), cancelToken); } catch (OperationCanceledException) { this._labelOutput.Text = "Задача отменена."; } catch (Exception ex) { this._labelOutput.Text = $"В задаче произошла ошибка: {ex.Message}"; } }
//Отмена private void _buttonCancel_Click(object sender, EventArgs e) { _tokenSource.Cancel(); }
//Эта самая долгая задача, обратите внимание на тип параметра progess он IProgress private string DoSomething(CancellationToken cancelToken, IProgress progess) { for (int i = 0; i < 6; i++) { //сообщаем о прогрессе progess.Report($"Этап: {i}");
//задержка между этапами 1 сек. cancelToken.WaitHandle.WaitOne(TimeSpan.FromSeconds(1));
//здесь будет выброшено исключение в случае нажатия на кнопку отмены cancelToken.ThrowIfCancellationRequested(); }
return "Готово!"; } }

Комментариев нет:

Отправить комментарий