У меня возникли проблемы, когда я жду задания после того, как я отменил его с помощью CancellationTokenSource. Вызов отмены не прерывает задачу. Когда я жду для задачи, основная часть потока блокируется, потому что задача никогда не прерывается.CancellationTokenSource misbehavior
Краткое описание моей программы: Задача увеличивает переменную char (от 'A' до 'Z') и показывает ее в потоке графического интерфейса. Для этого задача выполняет делегат (this.invoke()) в потоке, на котором был создан элемент управления.
Как только я прокомментирую функцию RefreshTextBox() - функция отменяет звонок, и задача будет прервана. Кажется, что команда this.invoke() предотвращает прерывание задачи.
Я код ниже, я также реализовал ту же функциональность с нормальными потоками. И затем я работаю. Где разница между реализацией задачи и реализацией потоков?
using System.Windows.Forms;
using System.Threading;
using System.Threading.Tasks;
public partial class frm_Main : Form
{
private delegate void dgt_StringHandler(string str_Value);
CancellationTokenSource _obj_Cts = null;
Thread _obj_Thread = null;
Task _obj_Task = null;
public frm_Main()
{
InitializeComponent();
}
private void CreateChar(ref char chr_Value)
{
int int_Value;
int_Value = (int)chr_Value;
int_Value++;
if (int_Value > 90 || int_Value < 65)
int_Value = 65;
chr_Value = (char)int_Value;
}
private void TestThread()
{
char chr_Value = '@';
bool bol_Stop = false;
while (!bol_Stop)
{
try
{
Thread.Sleep(300);
CreateChar(ref chr_Value);
RefreshTextBox(chr_Value.ToString());
}
catch (ThreadInterruptedException)
{
bol_Stop = true;
}
}
}
private void TestTask(object obj_TokenTmp)
{
char chr_Value = '@';
CancellationToken obj_Token = (CancellationToken)obj_TokenTmp;
while (!obj_Token.IsCancellationRequested)
{
Thread.Sleep(300);
CreateChar(ref chr_Value);
RefreshTextBox(chr_Value.ToString());
}
}
private void RefreshTextBox(string str_Value)
{
if (txt_Value.InvokeRequired)
{
dgt_StringHandler obj_StringHandler = new dgt_StringHandler(RefreshTextBox);
this.Invoke(obj_StringHandler, new object[] { str_Value });
}
else
{
txt_Value.Text = str_Value;
}
}
private void btn_StartStop_Click(object sender, EventArgs e)
{
if (_obj_Task == null && _obj_Thread == null)
{
if (opt_Task.Checked)
{
_obj_Cts = new CancellationTokenSource();
_obj_Task = new Task(new Action<object>(TestTask), _obj_Cts.Token, _obj_Cts.Token);
_obj_Task.Start();
}
else
{
_obj_Thread = new Thread(new ThreadStart(TestThread));
_obj_Thread.Start();
}
btn_StartStop.Text = "Stop";
}
else
{
if (_obj_Thread != null)
{
_obj_Thread.Interrupt();
_obj_Thread.Join();
_obj_Thread = null;
}
if (_obj_Task != null)
{
_obj_Cts.Cancel();
_obj_Task.Wait();
_obj_Task = null;
_obj_Cts = null;
}
btn_StartStop.Text = "Start";
}
}
}
Благодарим вас за ответ. Но это не решение проблемы. Я хочу знать, почему я не могу отменить его с помощью CancellationTokenSource. Когда я комментирую оператор Wait, задача все еще выполняется (или в моем случае блокировка) в фоновом режиме и никогда не подходит к концу. –
Мне непонятно, почему одни и те же подпрограммы работают с обычным потоком при вызове Interrupt(), а затем Join(). И когда я реализую его с заданием и вызываю Cancel(), а затем Wait(), он не работает. Где разница. Когда я комментирую метод refreshbox(), функции Cancel() и Wait() также работают с реализацией задачи! –
«задача все еще запущена» - тогда это ваша проблема. Отмена - это совместное действие. Ваша задача должна прекратиться и воздержаться. Thread.Interrupt (или .Abort) является мощным, но небезопасным. –