我正在尝试退出表单。但在退出之前,我需要确保一些无限任务已停止。这是我所拥有的一个最小的例子。
public partial class Form1 : Form {
private CancellationTokenSource _cts;
private Task _backgroundTask;
public Form1() {
InitializeComponent();
_cts = new CancellationTokenSource();
_backgroundTask = Task.Run(() => DoWork(_cts.Token));
}
private async Task DoWork(CancellationToken token) {
while (true) {
try {
token.ThrowIfCancellationRequested();
await Task.Delay(1);
Debug.Write(">");
Invoke(() => { Text = DateTime.Now.ToString(); });
Debug.WriteLine("<");
} catch (OperationCanceledException) {
// Expected
break;
} catch (InvalidOperationException ex) {
// Not expected
;
}
}
}
private async void button1_Click(object sender, EventArgs e) {
_cts.Cancel();
await _backgroundTask;
Debug.WriteLine("CLOSE");
Close();
}
有时代码会抛出
InvalidOperationException
并显示以下消息:
Invoke or BeginInvoke cannot be called on a control until the window handle has been created.
调试输出为:
><
><
><
Exception thrown: 'System.OperationCanceledException' in System.Private.CoreLib.dll
CLOSE
>Exception thrown: 'System.InvalidOperationException' in System.Windows.Forms.dll
推荐的解决方法似乎是只对异常进行空捕获,但我想知道为什么会发生这种情况?等待调用后循环如何继续运行?
在任意线程中执行 WinForms 方法时,使用
Invoke
:
private async void button1_Click(object sender, EventArgs e) {
_cts.Cancel();
await _backgroundTask;
Debug.WriteLine("CLOSE");
// Close - Win Forms method - should be called in the main thread context
this.Invoke(Close);
}