【发布时间】:2020-03-22 08:12:44
【问题描述】:
我正在开发一个大型 WinForms 项目,该项目在同一个 UI 线程上控制多个表单。
其中一些表单能够从数据库中获取和分析一些数据,这是使用 await 完成的(在等待数据并分析数据时不会冻结所有表单)。
我想确保当 UI 线程在已处理的表单中等待之后继续时我没有问题(如果用户在 Task 仍在运行时关闭了表单)。
我在谷歌上搜索了一下,找到了这个:
How to better handle disposed controls when using async/await
作者在此页面中写道,在上述情况下会引发异常(当 UI 线程尝试访问已处置形式的标签时)。
我对这种情况进行了测试,但没有抛出任何异常:
public partial class Simple_Form : Form
{
public Simple_Form()
{
InitializeComponent();
}
public async Task startCheck(Form1 caller)
{
caller.richTextBox1.Text += "Thread:" + Thread.CurrentThread.ManagedThreadId.ToString() + "|start\n";
label1.Text = "Thread:" + Thread.CurrentThread.ManagedThreadId.ToString() + "|start";
await Task.Delay(10000);
caller.richTextBox1.Text += "Thread:" + Thread.CurrentThread.ManagedThreadId.ToString() + "|stop\n";
caller.richTextBox1.Text += "Thread:" + Thread.CurrentThread.ManagedThreadId.ToString() + "|" + label1.IsDisposed + "\n";
label1.Text = "Thread:" + Thread.CurrentThread.ManagedThreadId.ToString() + "|stop";
}
当 UI 线程处于等待状态时,我尝试运行 StartCheck 并关闭 Simple_Form 表单。
尽管 UI 线程尝试更改 Disposed 标签 (label1),但此代码运行时未引发任何异常,label1.IsDisposed 为“true”。
我是否遗漏了某些内容,或者自创建上述页面以来此功能是否发生了变化?
编辑:
根据要求,我运行的主要形式:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Simple_Form newForm;
private async void button2_Click(object sender, EventArgs e)
{
newForm = new Simple_Form();
newForm.Show();
await newForm.startCheck(this);
return;
}
private void button1_Click(object sender, EventArgs e)
{
newForm.Dispose();
}
private void button3_Click(object sender, EventArgs e)
{
richTextBox1.Text += "Thread:" + Thread.CurrentThread.ManagedThreadId.ToString() + "|Still alive.\n";
}
}
我正在通过单击 button2 创建 Simple_Form。
我尝试通过单击 button1 或单击 Simple_Form 表单上的“X”按钮来处理它,这两种方式都可以正常工作,而不会引发任何异常。
编辑 2:按照建议更改了代码,原来的问题仍然存在。
【问题讨论】:
-
你怎么称呼
StartCheck?你能在你实际调用Dispose()表单的地方展示使用吗? -
没问题,我编辑了原帖。
-
您应该收到关于不等待
newForm.startCheck(this);的警告,startCheck方法应该返回Task -
@Fabio 我刚刚用一个简单的(和同步的 POC)进行了验证。已处置的 Label 允许对其 Text 属性进行分配。
-
@Oguz Ozgul,所以在这种情况下更改标签文本不会抛出异常,在上述情况下,什么变化之王会抛出异常?我不知道是否必须检查 this.IsDisposed 在每次等待后确保在用户关闭表单或不需要时不会抛出异常(我不在乎代码是否会继续运行如果它最终没有任何问题结束,则在后台)。
标签: c# multithreading winforms dispose