如何在调用无参数Application.Run()的线程中运行代码?

时间:2013-10-15 13:50:19

标签: winforms devexpress

我想通过WiForm DevExpress ChartControl函数在单独的帖子上使用DrawToBitmap()呈现图表。

我试着像:

Form yourForm;
Thread thread = new Thread( () =>
{
     yourForm = new HiddenForm();
     Application.Run(yourForm);
});
thread.ApartmentState = ApartmentState.STA;
thread.Start();
yourForm.Invoke(chartRenderingFunction)

简单地确保隐藏的实际上从未显示过。但是,我不需要隐藏的形式,并且有一个无参数形式的Application.Run()。但是,如果我运行它,它不会返回。所以我的问题是,一旦我在一个线程中调用Application.Run(),我该如何在其中注入代码?

1 个答案:

答案 0 :(得分:3)

嗯,你真的确实需要那个隐藏的窗口。获取代码在该线程上运行的唯一方法。有人必须调用PostMessage(),这需要一个窗口句柄。您的Invoke()调用进行该调用。你真的应该使用BeginInvoke(),如果要等待调用完成,启动一个线程是没有意义的。

使用Application.Run(yourForm)将使窗口可见。您可以通过覆盖HiddenForm类中的SetVisibleCore()方法来阻止它变得可见:

protected override void SetVisibleCore(bool value) {
    if (!this.IsHandleCreated) {
        CreateHandle();
        value = false;
        ThreadReady.Set();
    }
    base.SetVisibleCore(value);
}

CreateHandle()调用是必要的,以确保创建窗口,以便它可以处理PostMessage()通知。另请注意添加的AutoResetEvent(ThreadReady),在调用线程的Start()方法之后,您必须调用ThreadReady.WaitOne()以确保您的BeginInvoke()调用能够正常工作。处理表单以使线程退出或调用Application.Exit()。

最后但并非最不重要的是,非常小心使用该线程上的非平凡控件。当然没有指出图表控件。如果该控件使用SystemEvents类,那么您将遇到持久的问题。您的工作线程将使其在该工作线程上引发事件。但是在打印图表后它不会再出现了。你现在将获得在任意线程池线程上触发的事件,非常讨厌。死锁是一种常见的事故,特别是在锁定工作站时会触发。