从另一个类中的另一个线程创建和显示 WindowsForm - C# [关闭]

Posted

技术标签:

【中文标题】从另一个类中的另一个线程创建和显示 WindowsForm - C# [关闭]【英文标题】:Creating and showing a WindowsForm from another Thread in another class - C# [closed] 【发布时间】:2021-05-04 13:18:37 【问题描述】:

首先:我知道这个问题已经被问过很多次了,但我确实在这个问题上停滞了几个小时,并且我没有成功地将我发现的不同解决方案应用到我的问题。

我有一个这样的课程:

class Program

    private static UDProtocol MyUdp;

    [STAThread]
    static void Main()
    
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        MyUdp = new UDProtocol();
        MyUdp.Start();
        Application.Run();
    

还有一个类 UDProtocol,我将其简化如下:

class UDProtocol

    UdpMe = new UdpClient(11000);

    public void Start()
    
        new Thread(() =>
        
            CreateNewForm();

        ).Start();
     

    public void CreateNewForm()
    
        //Form f1 = new Form()
        //f1.Show()
    
  

当我这样做时(使用 CreateNewForm 中的 cmets),我显示了我的表单,但它上面的控件都是透明的,如下所示:

我认为这是因为尝试在不同的线程中创建一个 from,我很确定我应该使用 Invoke,但我真的不知道该怎么做。

谢谢

编辑:解决方案

Application.Run(new Form());

在线程中添加这个可以解决问题。表格显示正确

【问题讨论】:

看起来与线程无关,表单是在单个线程上创建和访问的。我不明白,你想每毫秒创建一个新表单?? @Charlieface 我明白了,不,当我简化代码以便它专门针对问题可读时,这是一个错误,我将对其进行编辑。 WPF 和 Winforms 控件必须从 STA 线程(在本例中为应用程序的主线程)进行管理,如果您想从其他线程引发新的 Winforms 控件/表单/事件,您应该使用调度员。 这能回答你的问题吗? How to start a UI thread in C# 【参考方案1】:

UDProtocol 对象应生成自定义Form 可用于向用户显示信息的事件。

class Program 
    [STAThread]
    static void Main() 
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        MyForm f1 = new MyForm();
        Application.Run(f1);
    


public class UDProtocol 

    public event EventHandler SomeEvent;

    Thread tRead = null;
    public void Start() 
        // some internal thread starts
        if (tRead != null)
            throw new Exception("Already started.");

        tRead = new Thread(() => 
            while (true) 
                Thread.Sleep(1000);
                if (SomeEvent != null)
                    SomeEvent(this, EventArgs.Empty);
            
        );
        tRead.IsBackground = true;
        tRead.Name = "UDProtocol.Read";
        tRead.Start();
    


public class MyForm : Form 
    UDProtocol myUDP = new UDProtocol();

    public MyForm() 
        myUDP.SomeEvent += udp_SomeEvent;
    

    protected override void OnLoad(EventArgs e) 
        base.OnLoad(e);
        myUDP.Start();
    

    void udp_SomeEvent(object sender, EventArgs e) 
        this.BeginInvoke((Action) delegate 
            MessageBox.Show(this, "Some event happened in the UDP object.", "UDP Event");
        );
    

【讨论】:

以上是关于从另一个类中的另一个线程创建和显示 WindowsForm - C# [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

JavaFX 使用 Platform.runLater 从另一个线程更新 TextArea

从另一个线程捕获异常

如何从另一个线程更新 GUI 上的文本框 [重复]

如何从 Java 中的另一个线程更新 SWT GUI

在 Windows 中的另一个线程上异步启动和取消 I/O 的无竞争方式

从另一个类中的 UITextField 访问文本