我在使用CancellationTokenSource取消它後等待任務時出現問題。取消呼叫不會中斷任務。當我爲任務等待 時,主線程會阻塞,因爲任務不會中斷。CancellationTokenSource misbehavior
下面是我的程序的簡短說明: 任務將字符變量(從'A'增加到'Z')增加並在GUI線程中顯示它。爲了做到這一點,任務在創建控件的線程上執行委託(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)功能強大但不安全。 –