Can/Does WPF have multiple GUI threads?

匿名 (未验证) 提交于 2019-12-03 01:29:01

问题:

Can/Does WPF have multiple GUI threads? Or does it always only have one GUI thread (even if I have multiple windows/dialogs)?

I'm asking because I have events coming from other threads and I'd like to handle them in the GUI thread (because I need to modify the controls of my main window accordings to the events).

Btw: I know I need to use a Dispatcher object for this purpose. So, I could rephrase my question and ask: Is there always only one Dispatcher object for all GUI elements in WPF?

回答1:

Based on the link in the first answer I did some verification on my own. I'd like to share the results here. First of all:

There can be multiple GUI threads (and therefor multiple Dispatcher instances).

However:

Simply creating a new window (modal or not) does not create a new GUI thread. One needs to create the thread explicitly (by creating a new instance of Thread).

Note: Instead of using separate threads, modal dialogs are likely being realized by using Dispatcher.PushFrame() which blocks the caller of this method while still allowing events to be dispatched.

I've created a simple WPF class (again, based on the link from the first answer) to verify all this stuff. I share it here so you can play around with it a little bit.

MainWindow.xaml:

        

MainWindow.xaml.cs:

using System; using System.Threading; using System.Windows; using System.Windows.Media;  namespace WindowThreadingTest {   ///    /// Interaction logic for MainWindow.xaml   ///    public partial class MainWindow : Window {     private static uint s_windowNumber = 0;      private readonly MainWindow m_prevWindow;      public MainWindow() : this(null) { }      public MainWindow(MainWindow prevWindow) {       InitializeComponent();        this.m_prevWindow = prevWindow;        this.Title = String.Format("Window {0}", ++s_windowNumber);        Thread thread = Thread.CurrentThread;       this.m_threadId.Text = thread.ManagedThreadId.ToString();       this.m_threadTA.Text = thread.GetApartmentState().ToString();     }      private void OnCreateNewWindow(object sender, RoutedEventArgs e) {       CreateNewWindow(true, false, true);     }      private void CreateNewWindow(bool newThread, bool modal, bool showInTaskbar) {       MainWindow mw = this;        if (newThread) {         Thread thread = new Thread(() => {           MainWindow w = new MainWindow(this);           w.ShowInTaskbar = showInTaskbar;            if (modal) {             // ShowDialog automatically starts the event queue for the new windows in the new thread. The window isn't             // modal though.             w.ShowDialog();           } else {             w.Show();             w.Closed += (sender2, e2) => w.Dispatcher.InvokeShutdown();             System.Windows.Threading.Dispatcher.Run();           }         });          thread.SetApartmentState(ApartmentState.STA);         thread.Start();        } else {         MainWindow w = new MainWindow(this);         w.ShowInTaskbar = showInTaskbar;         if (modal) {           // Even modal dialogs run in the same thread.           w.ShowDialog();         } else {           w.Show();         }       }     }      private void OnAccessTest(object sender, RoutedEventArgs e) {       if (m_prevWindow == null) {         return;       }        this.Background = Brushes.Lavender;       try {         m_prevWindow.Background = Brushes.LightBlue;       } catch (InvalidOperationException excpt) {         MessageBox.Show("Exception: " + excpt.Message, "Invalid Operation");       }       m_prevWindow.Dispatcher.Invoke((Action)(() => m_prevWindow.Background = Brushes.Green));        this.Dispatcher.Invoke((Action)(() => {         try {           m_prevWindow.Background = Brushes.Red;         } catch (InvalidOperationException excpt) {           MessageBox.Show("Exception: " + excpt.Message, "Invalid Dispatcher Operation");         }       }));     }   } } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!