界面:一个BtnStart,一个TxtInfo。不断地追加文本信息。
代码如下:
private CancellationTokenSource cts = new CancellationTokenSource();
private void BtnStart_Click(object sender, EventArgs e)
{
CancellationToken ct = cts.Token;
Task.Run(() =>
{
int idx = 0;
while (!ct.IsCancellationRequested)
{
Invoke(new Action(() =>
{
TxtInfo.AppendText($"[{++idx}]-----\r\n");
}));//a
Thread.Sleep(100);//b
}
}, ct);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{ cts.Cancel(); }
点击开始后,程序跑起来,这时直接关闭form1,会在a处报错,因为UI已经关闭,再用invoke会出错。
这里可以用begininvoke来取代 invoke,因为beginvoke有检测取消的功能。所以这时不会报错。
问题在于:
不允许用beginvoke情况下,如何不报错的关闭form1呢?
(因为另一个例子中,用B线程控制A线程时,有标志位置-1索引情况,如果用begininvoke在消息排列时,滞后访问这个标志位,可能为-1,会导致索引超出,所以不得已不能用begininvoke)
试了几个小时没搞对。
目前有两个解决办法,但没有明白原因:
(1)在task.run(后面直接加async,哪怕thread.sleep(1)秒也不会报错。
Task.Run(async () =>
{
int idx = 0;
while (!ct.IsCancellationRequested)
{
Invoke(new Action(() =>
{
TxtInfo.AppendText($"[{++idx}]-----\r\n");
}));//a
Thread.Sleep(1);//b
}
}, ct);
疑问:async需要和await配套才能是异步,这里仅仅一个async仍然按同步执行,应该等同于没有加,为什么不在a处报错?
(2)在异步线程中再异步执行等待,哪怕1毫秒也不会报错.
Task.Run(async () =>
{
int idx = 0;
while (!ct.IsCancellationRequested)
{
Invoke(new Action(() =>
{
TxtInfo.AppendText($"[{++idx}]-----\r\n");
}));//a
await Task.Delay(1);//b
}
}, ct);
疑问:明明用了 token来进行取消判断,当收到取消时,异步线程收到信息后会把当前逻辑代码块执行完成后(哪怕是invoke)就应该立即取消,所以用Thread.sleep应该不会影响UI线程,现在这里用了异步等待await task.delay(1),明显说明thread有影响。。。。为什么?
想不通,请高手指明上面两个疑惑?
代码如下:
private CancellationTokenSource cts = new CancellationTokenSource();
private void BtnStart_Click(object sender, EventArgs e)
{
CancellationToken ct = cts.Token;
Task.Run(() =>
{
int idx = 0;
while (!ct.IsCancellationRequested)
{
Invoke(new Action(() =>
{
TxtInfo.AppendText($"[{++idx}]-----\r\n");
}));//a
Thread.Sleep(100);//b
}
}, ct);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{ cts.Cancel(); }
点击开始后,程序跑起来,这时直接关闭form1,会在a处报错,因为UI已经关闭,再用invoke会出错。
这里可以用begininvoke来取代 invoke,因为beginvoke有检测取消的功能。所以这时不会报错。
问题在于:
不允许用beginvoke情况下,如何不报错的关闭form1呢?
(因为另一个例子中,用B线程控制A线程时,有标志位置-1索引情况,如果用begininvoke在消息排列时,滞后访问这个标志位,可能为-1,会导致索引超出,所以不得已不能用begininvoke)
试了几个小时没搞对。
目前有两个解决办法,但没有明白原因:
(1)在task.run(后面直接加async,哪怕thread.sleep(1)秒也不会报错。
Task.Run(async () =>
{
int idx = 0;
while (!ct.IsCancellationRequested)
{
Invoke(new Action(() =>
{
TxtInfo.AppendText($"[{++idx}]-----\r\n");
}));//a
Thread.Sleep(1);//b
}
}, ct);
疑问:async需要和await配套才能是异步,这里仅仅一个async仍然按同步执行,应该等同于没有加,为什么不在a处报错?
(2)在异步线程中再异步执行等待,哪怕1毫秒也不会报错.
Task.Run(async () =>
{
int idx = 0;
while (!ct.IsCancellationRequested)
{
Invoke(new Action(() =>
{
TxtInfo.AppendText($"[{++idx}]-----\r\n");
}));//a
await Task.Delay(1);//b
}
}, ct);
疑问:明明用了 token来进行取消判断,当收到取消时,异步线程收到信息后会把当前逻辑代码块执行完成后(哪怕是invoke)就应该立即取消,所以用Thread.sleep应该不会影响UI线程,现在这里用了异步等待await task.delay(1),明显说明thread有影响。。。。为什么?
想不通,请高手指明上面两个疑惑?