【问题标题】:Using Application.Run() on different threads在不同的线程上使用 Application.Run()
【发布时间】:2009-08-03 14:57:28
【问题描述】:

请看下面的代码:

var splashForm = new SplashForm();
m_Thread = new Thread( () => System.Windows.Forms.Application.Run( splashForm ) )
m_Thread.Start();

// Do some initialization
// ...

// the following method just invokes `Close()` on the right thread
splashForm.Shutdown();

// Loop until the thread is no longer alive
// ...

System.Windows.Forms.Application.Run( mainForm );

看起来一切正常:首先我看到启动画面,然后主窗体启动。但不知何故,我遇到了奇怪的错误,例如:图形元素(无尽的 ProgressBar)没有正确显示。
编辑:我有两个进度条,一个在启动画面上,一个在主窗体上。它们在无尽模式下都表现出相同的(错误)行为:没有进展,只有纯背景。/EDIT
在我看来,这是由于在不同线程上调用了Application.Run()。可以通过在启动闪屏之前调用 mainForm 的任何函数/属性来消除此错误 - 例如,

mainForm.Text = mainForm.Text;

任何人都可以确认此代码是否会导致问题 - 或者它应该表现良好,我必须在其他地方查找错误?
我已经寻找了启动画面的实现,并且我知道它可以以不同的方式完成。但我有兴趣了解这种实现及其可能的问题。谢谢!

【问题讨论】:

    标签: c# multithreading


    【解决方案1】:

    您的 SplashForm 显示的线程需要有一个 Windows 消息泵,以便处理每个窗口/控件产生的消息消耗。为此,您需要使线程成为 STA 线程。尝试调用SetApartmentState启动线程

    【讨论】:

    【解决方案2】:

    我会Application.Run() 执行的线程上创建表单。

    SplashForm splashForm = null;
    m_Thread = new Thread(delegate { splashForm = new SplashForm(); System.Windows.Forms.Application.Run(splashForm); });
    m_Thread.Start();
    

    但真正需要做的是通过 InvokeRequired 和 BeginInvoke 技术访问它。检查here

    【讨论】:

    • 嗯,这只是一半。正如链接文章所建议的那样,主要部分实际上是 InvokeRequired 部分。
    • 我已经使用 RevokeInquired ...这就是我使用 Shutdown() 的原因 - 它只调用 Close() 方法。
    【解决方案3】:

    我的天啊,我找到了答案:
    Application.EnableVisualStyles(); 在我的 mainForm 中被调用(为什么?)。必须在创建任何控件之前调用它。把它移到static Main() 就行了。无尽的 (ProgressBarStyle.Marquee) 进度条需要视觉样式。
    现在这个闪屏解决方案可以正常工作了。

    【讨论】:

    • 这可能对你有用。但是,我会做的有点不同。我假设您只想在加载期间显示启动画面。那么为什么要为创建启动画面的线程创建消息泵。相反,只需通过调用 Show 在单独的线程上调用它,完成后,只需调用 close。现在,通过调用 Application.Run(mainForm) 创建消息泵
    • 是的,你可能是对的。可能会跳过对 Application.Run() 的附加调用,我会检查一下。
    【解决方案4】:

    你所做的基本上没有错。我发现这种方法很有趣,可以制作一个演示,而且效果很好。我也可以说kek444的答案不是问题。在主线程上创建 SplahForm 没有任何区别。

    所以我猜这是您控制进度条的方式,或者更一般地说是您在 2 个线程之间进行通信的方式。

    【讨论】:

    • 在闪屏上有一个进度条 - 在连续模式下它不显示任何进度(只是背景)。稍后在主窗体中也有一个进度条,它在无限模式下显示相同的行为:没有...
    • 我正在计时器上运行 PBar - 没问题。你如何推动新的价值观?
    • 我不是在推送值 - 我只是将样式设置为 ProgressBarStyle.Marquee。
    • 我发现了问题所在 - 非常抱歉,因为你甚至写了一个演示......:/请看我的回答。
    猜你喜欢
    • 1970-01-01
    • 2021-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多