如果主線程是STA並創建一個Window,則向它添加一些UI元素。然後產生另一個STA線程,第二個線程同樣創建一些UI元素,他們是否在同一個'空間'[snip ...]中執行它,並且可以訪問對方的UI元素而不會導致死亡和破壞?
如果線程A和B都是STA,那麼他們可以各自創建和更新其自己 UI元素,但不是eachothers。任何其他想要影響UI的線程都必須使用BeginInvoke
樣式方法之一來請求相應的線程進行更新。
如果沒有必要,那麼我只會讓該工作線程成爲STA線程並繼續行進,這是否公平?或者我在追求災難?
如果已將工作線程設置爲MTA並初始化,您可能無法將工作線程作爲STA線程。你可能不得不做一個新的線程。
你怎麼做到的?看起來你想爲你的UI使用WPF(System.Windows.*
) - 所以如果你「插入」的應用程序也使用WPF,你應該可以訪問它並重用它的UI線程。如果沒有,您可以創建一個新線程,並在其上創建一個新的Application
並致電Run
。這應該爲你設置一個調度員。
是這樣的(僞代碼排序的一些工作的代碼複製我在其他地方)
Dispatcher dispatcher = null; // we 'get to' the UI thread via the dispatcher
if(Application.Current) { // re use an existing application's UI thread
dispatcher = Application.Current.Dispatcher;
} else {
var threadReadyEvent = new ManualResetEvent(false);
var uiThread = new Thread(() => {
Thread.CurrentThread.SetApartmentState(ApartmentState.STA);
var application = new Application();
application.Startup += (sender, args) => {
dispatcher = application.Dispatcher;
threadReadyEvent.Set();
};
// apps have to have a "main window" - but we don't want one, so make a stub
var stubWindow = new Window {
Width = 1, Height = 1,
ShowInTaskbar = false, AllowsTransparency = true,
Background = Brushes.Transparent, WindowStyle = WindowStyle.None
};
application.Run(stubWindow);
}){ IsBackground = true };
uiThread.Start();
threadReadyEvent.WaitOne();
threadReadyEvent.Dispose();
}
dispatcher.Invoke(() => {
// ask the UI thread to do something and block until it finishes
});
dispatcher.BeginInvoke(() => {
// ask the UI thread to do something asynchronously
});
等等
STA和MTA是相關的COM編程術語。你真的在做COM嗎?如果不是,那麼只關注保持UI線程安全的需要,並使用您用來編組調用的類庫提供的基本基元。 Winforms中的Control.Begin/Invoke(),WPF或Store應用程序中的Dispatcher.Begin/Invoke()。 –
這是我得到的錯誤: System.InvalidOperationException:調用線程必須是STA,因爲許多UI組件需要此。 因爲這個,我認爲它是一個STA/MTA問題。我沒有明確地使用任何COM(我知道),但是我正在爲一個(更多)更大的軟件寫一個插件,我知道它正在使用COM。 –
您應該更多地瞭解您正在編寫插件的那個「更大」的軟件的體系結構。一些應用程序具有多線程UI,其中每個主UI窗口位於其自己的線程中。僅舉幾例:MS Word,Windows資源管理器。您的主機應用程序可以這樣嗎? – Noseratio