2

因为这是一个相当大的项目,而且我经常需要从一个类中访问其他形式的对象,所以我首先在我的 program.cs 类型的“MainForm”类中创建一个静态变量,这是一个 Windows 窗体。

从我的 DataManger.cs 类中,我实例化对象“Program.MainFormObj = new MainForm()”,然后调用 Show 方法以显示我的表单。看起来窗体的 Paint 事件没有完成,但它确实在绘制一些控件时启动。大概是因为主线程(这一切都在一个主线程上运行)被下一条语句“占用”。我想,不管已知问题如何,我都会使用 Application.DoEvents() 来临时解决这个问题。正如我想象的那样,它起作用了,但只是在一定程度上。如果我使用像 MessageBox.Show() 这样的阻塞方法,我可以在后台查看我完全完美的表单,但只要我按下“确定”并且代码继续,整个应用程序就会退出。

我真的被困住了。尽管在这里和使用谷歌进行了广泛的搜索,但我找不到合适的答案。我做了这个线程:Form.Show() 没有显示它的子控件,但给定的解决方案不适合我的解决方案。非常感谢任何帮助,谢谢。

4

1 回答 1

2

如果这是一个大型项目,请立即投入时间对其进行重构。

  • 考虑一个 MVC 模式。您可以使用 WinForms 来做些什么,而不仅仅是更新的 UI 技术。
  • 如果你不选择 WinForms,至少要分离 UI 和数据(数据绑定是你的朋友)。
  • 当不同的表单共享通用功能时,构建可重用的组件。

与 WinForms 的工作方式作斗争在中期将比现在投入时间做正确的事情要昂贵得多。

如果您对该技术有任何选择,请考虑 WPF。WPF 有一个学习曲线,但现在可能值得投资于该学习。

更新

根据您的代码示例,我看到您可能正在主 UI 线程以外的线程上创建一些表单。虽然这是允许的,但它会创建非常混乱的代码,因为表单只能从创建它们的线程更新。

最简单的破解方法可能是更新HandleIncomingData以调用Show()主 UI 线程上的调用。

应该有一种方法可以从静态方法中干净地做到这一点,如下所述:

https://stackoverflow.com/a/505361/141172

但是,当我尝试这样做时,我发现它SynchronizationContext始终为空。我确定我只是少了一步。

我能够通过滥用LoginForm(假设,也许是错误的,该表单始终可用。如果没有,也许创建一个仅用于线程编组的特殊表单)。

黑客看起来像这样:

Program.MainForm = new MainForm();
try
{

    MessageBox.Show("Login Success.", "Login", MessageBoxButtons.OK, MessageBoxIcon.Information);

            // Abusing LoginForm's Invoke method.  Code assumes LoginForm is always available.
    Program.LoginForm.Invoke((MethodInvoker)delegate
    {
        Program.MainForm.Show();
    });


}
catch (Exception Ex)
{
    MessageBox.Show(Ex.ToString()); //Debuging purposes
}

顺便说一句,有一个出色的扩展方法可以让从非 UI 线程调用 UI 代码变得轻而易举:

https://stackoverflow.com/a/3588137/141172

于 2012-07-04T00:14:18.913 回答