我想要实现的是在长时间操作期间显示 FirstForm。 当此操作结束时,我想关闭 FirstForm和显示 SecondForm。 下面是示例代码:为了我的惊喜,Close无效(两种形式都可见)。
using System;
using System.Windows.Forms;
using System.Threading.Tasks;
namespace WindowsFormsApplication1
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FormMain());
}
}
class FormMain : Form
{
public FormMain()
{
var button = new Button() { Text = "test" };
button.Click += (o, e) =>
{
var first = new FormFirst();
Task.Factory.StartNew(() =>
{
////some long operation...
}).ContinueWith(t => {
first.Close();
var second = new FormSecond();
second.ShowDialog();
}, TaskScheduler.FromCurrentSynchronizationContext());
first.ShowDialog();
};
Controls.Add(button);
}
}
class FormFirst : Form
{
public FormFirst() { Text = "First"; }
}
class FormSecond : Form
{
public FormSecond() { Text = "Second"; }
}
}
我使用Form.Invoke解决了这个问题,但这是一种正确的方式吗?:
var first = new FormFirst();
Task.Factory.StartNew(() =>
{
////some long operation...
var created = new AutoResetEvent(first.IsHandleCreated);
first.HandleCreated += (o1,e1) => created.Set();
created.WaitOne();
first.Invoke(new Action(() => first.Close()));
}).ContinueWith(t =>
{
first.Close();
var second = new FormSecond();
...
答案 0 :(得分:0)
使用invoke
是正确的方法。
由于WinForms控件不是线程安全的,因此添加了this属性以确保可以访问表单方法的唯一线程是由它创建的。如果该属性设置为true,则直接从另一个线程调用表单的方法不起作用。现在,您可能将其设置为false并继续您的生活,但请注意,这存在的原因非常充分。
使用Form.Invoke
是您正在尝试实现的正确,线程安全的方法。如果您想进一步解释,可以参考this MSDN页面创建对WinForms控件的线程安全调用。另外,如果您有兴趣找到为什么这样,那么用户Adriano Repetti会在this回答中解释得非常好。