与程序同时运行表单

问题描述 投票:0回答:1

我有一个类试图创建一个更好的替代类

System.Console
类。事情是这样开始的:

public class SuperConsole
{
    private readonly Form _Form;
    public SuperConsole()
    {
        _Form = new()
        {
            Text = DefaultTitle,
            BackColor = DefaultBackColor,
        };
        Application.Run(_Form);
    }
    public string Title
    {
        get => _Form.Invoke(() => _Form.Text);
        set => _Form.Invoke(() => _Form.Text = value);
    }
    //more stuff
}

显然,如果我运行构造函数,它会冻结在

Application.Run
。当然,表单会运行,但构造函数的调用者必须稍等一下。因此,我更改了构造函数以在新线程上运行
Application.Run

public SmartConsoleWindow()
{
    _Form = new()
    {
        Text = DefaultTitle,
        BackColor = DefaultBackColor,
    };
    Thread t = new(() => Application.Run(_Form));
    t.Start();
}

但这会引发

System.InvalidOperationException
。可能有充分的理由。我有一种不好的预感,如果在第二个线程开始弄清楚
Title
之前访问
Application.Run
属性会发生什么。

我不知道如何继续。我尝试了几种变体,但没有效果。

我希望表单和调用函数能够同时运行,并且仍然能够正常使用

Form.Invoke
。我还希望该类的用户不必担心这些。我该怎么做?

欢迎任何建议!

c# multithreading winforms thread-safety invalidoperationexception
1个回答
0
投票

我认为你必须在专用的

Form
线程上创建
SuperConsole
,而不是在当前线程上,因为 UI 组件是线程仿射的。您还必须将
SuperConsole
线程声明为 STA,并等待表单创建。像这样的东西应该有效:

public class SuperConsole
{
    private Form _form;

    public SmartConsoleWindow()
    {
        ManualResetEventSlim mres = new();
        Thread t = new(() =>
        {
            _form = new()
            {
                Text = DefaultTitle,
                BackColor = DefaultBackColor,
            };
            mres.Set();
            Application.Run(_form);
        });
        t.Name = "SuperConsole";
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
        mres.Wait();
    }

    public string Title
    {
        get => _form.Invoke(() => _Form.Text);
        set => _form.Invoke(() => _Form.Text = value);
    }
}

ManualResetEventSlim
用于表示
Form
实例已创建,并分配给
_form
字段。否则,当前线程可能会观察到
_form
null

我没有测试过上面的代码。在消息循环开始之前,表单可能尚未准备好调用

Invoke
。在这种情况下,您可能需要将
mres.Set();
移动到表单的
Load
Shown
事件内。要了解如何仅订阅一个通知的事件,请参阅此答案

© www.soinside.com 2019 - 2024. All rights reserved.