[英]Winforms: One COM object needs an STAThread, the other needs an MTAThread. How can I use them?
[英]How do I test performance impact of [STAThread] in WinForms?
我設法用C#編寫了一個相對較大的WinForms應用程序,該應用程序在Main()
方法上沒有[STAThread]
屬性的情況下可以正常運行。
為此,我必須重寫許多WinForms功能(例如使用自定義的BeginInvoke
和Invoke
函數),使用自定義消息循環代替Application.Run
,使用自定義文件對話框代替OpenFileDialog
和SaveFileDialog
,並使用WM_DROPFILES拖放而不是WinForms開箱即用的OLE方法。 這都是“為了科學”。
現在,我想測試從所有GUI線程中刪除STAThreadAttribute可能對性能產生的影響。 我對Control類內部使用的COM配置沒有足夠的了解,無法預測這種影響。 執行速度可能取決於哪個線程正在調用Control
的內部COM對象。
誠然,我很難找到一個基准來測試與[STAThread]
有關的性能影響,因為我不確定哪些功能/操作會受到這種更改的影響(特別是與Control
類有關)。
我到底應該找什么? 我希望通過省略[STAThread]
(如果有)來期望Control
類中的哪些操作/方法運行更快/更慢?
附錄:理由是我正在慢慢地將我的應用程序遷移為使用自定義窗口系統(出於可移植性的原因,主要是因為在Linux上使用Mono,其WinForms實現尚未完成),因此無論如何我都不得不重寫許多功能。 只是巧合,我注意到我已經重寫了太多的功能,可以忽略[STAThread],並且一切仍然可以按預期進行。
由於來自ThreadPool
(配置為MTA)和GUI線程(默認情況下應配置為STA)的COM封送處理調用,我預計性能會有所變化。 由於在不同線程單元中配置了從ThreadPool
到GUI線程的調用,因此需要將它們編組,這會導致同步開銷。 通過將GUI線程保留為MTA,應減少編組,從而可能更快地執行函數調用。 我想以務實的方式對此要求進行檢驗。
[STAThread]具有過多的神秘感。 但是實際上很簡單,您就可以保證 。 跨過你的心,希望死。 您向操作系統保證,主線程是線程安全的好地方。 遵守承諾要求擁有調度程序(Application.Run),並且永遠不要阻塞線程。 您以后要做的事情,這就是為什么您必須提前做出承諾的原因。
在Windows上運行的GUI應用程序中,總是會有很多這樣的代碼。 無論使用哪種框架,此類代碼的位置都更加明顯。 但是,最糟糕的是您看不到的代碼。 在外殼擴展,UI自動化代碼中,希望通過剪貼板或拖放操作提供數據的應用中,SetWindowsHookEx附帶的掛鈎中,視力不佳的用戶的屏幕閱讀器中,期望PostMessage的ActiveX組件中都存在這種類型上班。 這樣的代碼不必一定是線程安全的,OS並不需要如此,主要是因為編寫該代碼的人無法對其進行測試。 他不了解您的應用程序。
這對OS很重要,因為當此類代碼未在UI線程上運行時,它必須執行某些操作。 由於代碼明確聲明它不是線程安全的或不是必須的,因此無論如何都必須確保代碼安全。 唯一可行的方法是初始化代碼,並在同一線程上對其進行任何將來的調用。 這需要一些技巧,代碼必須經過編組 ,使其可以在另一個線程上運行,而調度程序循環對於完成此工作至關重要。 調度員是生產者-消費者問題的通用解決方案。
但是,如果代碼是從正確的線程初始化的,則沒有必要。 操作系統如何知道它是否是“正確的線程”? [STAThread]承諾告訴了這一點。
因此,您可以得出的第一個結論是不將UI線程標記為STA,因為它實際上會使您的程序變慢 。 由於每個電話都被編組。 這不是唯一的問題,有很多這樣的代碼無法編組。 作者必須做額外的工作才能啟用它,他必須提供代理/存根。 有時這太難了,但他卻根本不這樣做,因為他依靠您來正確地做。 因此,通話將失敗。 但這是在外部代碼中發生的,您不會發現。 所以東西就是行不通的。 或僵局。 否則不會引發預期的事件。 慘的東西。 您必須使用[STAThread]避免痛苦。
否則,這是純Windows實現的詳細信息,在Unixes上不存在。 他們提供這些功能的方式完全不同(如果有的話)。 因此,[STAThread]在這樣的操作系統上並不意味着任何事情,並且在沒有它的情況下進行測試不會告訴您任何事情。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.