2013-10-15 36 views
0

我想在單獨的線程上通過WiForm DrawToBitmap()函數呈現帶有DevExpress ChartControl的圖表。如何在調用無參數Application.Run()的線程中運行代碼?

我嘗試類似:

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(),我該如何注入代碼?

+0

你想要達到什麼目的?我不明白HiddenForm的純文字? –

+0

@JensKloster我的圖表需要很長時間(秒)才能渲染。如果我將它渲染到主線程中的圖像,則在這些秒內窗口不響應。這不是一個好的用戶體驗。 –

回答

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類,則會遇到長期問題。你的工作線程會讓它在該工作線程上產生事件。但是在圖表打印後它不會再存在。你現在將得到在任意線程池線程上觸發的事件,非常討厭。死鎖是一種常見的不幸事件,特別容易在鎖定工作站時觸發。

+0

關於這些事件,如果我在呈現圖像後處理我的控件,該怎麼辦?任何事件會在那個時候開火嗎?如果情況並非如此,我能不能讓這條消息一直貫穿整個過程?我確定。 –

+0

SystemEvents事故不受線程運行或不運行的影響,只要UI窗口的其餘部分保持活動狀態,它仍會在錯誤線程上觸發。我不會承諾麻煩,只是警告你。 –

+0

我有點困惑,可能對某事不瞭解。我只想在控件上調用[Control.DrawToBitmap()](http://msdn.microsoft.com/en-us/library/system.windows.forms.control.drawtobitmap.aspx),然後將控件。 System.Drawing.Bitmap根本不與消息泵進行交互。它以獨立於設備的方式保存圖像數據(或者說每個GDI描述都如此)。 (1)對於ChartControl的短生命週期或(2)在位圖對象的生命週期中提出系統事件時,我是否處於危險之中? –

相關問題