如何从另一个线程关闭Form.ShowDialog,然后显示第二个窗体。

时间:2017-05-16 19:00:01

标签: c# winforms

我想要实现的是在长时间操作期间显示 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();
    ...

1 个答案:

答案 0 :(得分:0)

使用invoke是正确的方法。

由于WinForms控件不是线程安全的,因此添加了this属性以确保可以访问表单方法的唯一线程是由它创建的。如果该属性设置为true,则直接从另一个线程调用表单的方法不起作用。现在,您可能将其设置为false并继续您的生活,但请注意,这存在的原因非常充分。

使用Form.Invoke是您正在尝试实现的正确,线程安全的方法。如果您想进一步解释,可以参考this MSDN页面创建对WinForms控件的线程安全调用。另外,如果您有兴趣找到为什么这样,那么用户Adriano Repetti会在this回答中解释得非常好。