2011-04-19 18 views
24

क्या डब्ल्यूपीएफ में कई जीयूआई धागे हो सकते हैं? या क्या यह हमेशा एक जीयूआई धागा होता है (भले ही मेरे पास एकाधिक खिड़कियां/संवाद हों)?क्या डब्ल्यूपीएफ में कई जीयूआई धागे हो सकते हैं?

मैं पूछ रहा हूं क्योंकि मेरे पास अन्य धागे से आने वाली घटनाएं हैं और मैं उन्हें जीयूआई थ्रेड में संभालना चाहता हूं (क्योंकि मुझे घटनाओं में मेरी मुख्य विंडो समझौते के नियंत्रण को संशोधित करने की आवश्यकता है)।

बीटीडब्ल्यू: मुझे पता है कि मुझे इस उद्देश्य के लिए Dispatcher ऑब्जेक्ट का उपयोग करने की आवश्यकता है। तो, मैं अपने प्रश्न को दोबारा लिख ​​सकता हूं और पूछ सकता हूं: क्या WPF में सभी जीयूआई तत्वों के लिए हमेशा एक ही ऑब्जेक्ट है?

+1

आप WPF सूत्रण मॉडल प्रलेखन पढ़े हैं? http://msdn.microsoft.com/en-us/library/ms741870.aspx –

उत्तर

25

पहले उत्तर में दिए गए लिंक के आधार पर मैंने अपने आप पर कुछ सत्यापन किया था। मैं यहां परिणाम साझा करना चाहता हूं। सबसे पहले:

कई जीयूआई थ्रेड (और कई Dispatcher उदाहरणों के लिए) हो सकते हैं।

हालांकि:

, बस एक नई विंडो (मोडल या नहीं) बनाने एक नया जीयूआई सूत्र नहीं बनाया है। किसी को धागे को स्पष्ट रूप से बनाने की आवश्यकता है (Thread का नया उदाहरण बनाकर)।

नोट: इसके बजाय अलग धागे का उपयोग करने का, मोडल संवाद की संभावना Dispatcher.PushFrame() जो ब्लॉक इस विधि के फोन करने वाले, जबकि अभी भी घटनाओं की इजाजत दी भेज दिया उपयोग करके एहसास हुआ जा रहा है।

मैंने इन सभी चीजों को सत्यापित करने के लिए एक सरल WPF कक्षा (फिर से, पहले उत्तर से लिंक के आधार पर) बनाई है। मैं इसे यहां साझा करता हूं ताकि आप इसके साथ थोड़ा सा खेल सकें।

MainWindow.xaml:

<Window x:Class="WindowThreadingTest.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Width="250" Height="130"> 
    <StackPanel> 
    <StackPanel Orientation="Horizontal"> 
     <TextBlock Text="Thread's ID is "/> 
     <TextBlock x:Name="m_threadId"/> 
    </StackPanel> 
    <StackPanel Orientation="Horizontal"> 
     <TextBlock Text="Thread's threading apartment is "/> 
     <TextBlock x:Name="m_threadTA"/> 
    </StackPanel> 
    <Button Click="OnCreateNewWindow" Content="Open New Window"/> 
    <Button Click="OnAccessTest" Content="Access Test"/> 
    </StackPanel> 
</Window> 

MainWindow.xaml.cs:

using System; 
using System.Threading; 
using System.Windows; 
using System.Windows.Media; 

namespace WindowThreadingTest { 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    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"); 
     } 
     })); 
    } 
    } 
} 
+0

ठीक है अगर आप नहीं कर सके तो आप +1 नहीं कर सके – CloudyMarble

संबंधित मुद्दे