在不同的线程上使用Application.Run()

时间:2009-08-03 14:57:28

标签: c# multithreading

请查看以下代码:

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;

任何人都可以确认此代码可能会导致问题 - 或者它应该运行正常,我必须在其他地方查找错误吗?
我已经看过了flashscreen实现,我知道它可以以不同的方式完成。但我有兴趣了解这个实现及其可能存在的问题。谢谢!

4 个答案:

答案 0 :(得分:4)

SplashForm显示的线程需要有一个Windows消息泵才能处理每个窗口/控件产生的消息。要做到这一点,你需要使线程成为一个STA线程。尝试在启动帖子之前调用SetApartmentState

答案 1 :(得分:3)

我会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

答案 2 :(得分:1)

你正在做的事情没有任何问题。我发现这个方法很有趣,可以用来制作一个演示,但它运行正常。我还可以说kek444的答案不是问题。在主线程上创建SplahForm没有任何区别。

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

答案 3 :(得分:1)

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