<Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MultiBrowse" Height="600" Width="800" Loaded="OnLoaded"> <StackPanel Name="Stack" Orientation="Vertical"> <StackPanel Orientation="Horizontal"> <Button Content="New Window" Click="NewWindowHandler" /> <TextBox Name="newLocation" Width="500" /> <Button Content="GO!" Click="Browse" /> </StackPanel> <Frame Name="placeHolder" Width="800" Height="550"></Frame> </StackPanel> </Window> //File:Window.xaml.cs using System; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Threading; using System.Threading; namespace WpfApplication1 { public partial class Window1 : Window { public Window1() : base() { InitializeComponent(); } private void OnLoaded(object sender, RoutedEventArgs e) { placeHolder.Source = new Uri("http://www.kutayzorlu.com/java2s/com"); } private void Browse(object sender, RoutedEventArgs e) { placeHolder.Source = new Uri(newLocation.Text); } private void NewWindowHandler(object sender, RoutedEventArgs e) { Thread newWindowThread = new Thread(new ThreadStart(ThreadStartingPoint)); newWindowThread.SetApartmentState(ApartmentState.STA); newWindowThread.IsBackground = true; newWindowThread.Start(); } private void ThreadStartingPoint() { Window1 tempWindow = new Window1(); tempWindow.Show(); System.Windows.Threading.Dispatcher.Run(); } } }
Windows Presentation Foundation
Keep the UI from becoming non-responsive in single threaded application which performs a long operation.
<Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Prime Numbers" Width="260" Height="75"> <StackPanel Orientation="Horizontal" VerticalAlignment="Center" > <Button Content="Start" Click="StartOrStop" Name="startStopButton" Margin="5,0,5,0"/> <TextBlock Margin="10,5,0,0">Number:</TextBlock> <TextBlock Name="numberTextBlock" Margin="4,5,0,0">3</TextBlock> </StackPanel> </Window> //File:Window.xaml.cs using System; using System.Windows; using System.Windows.Controls; using System.Windows.Threading; using System.Threading; namespace WpfApplication1 { public partial class Window1 : Window { public delegate void NextPrimeDelegate(); private long num = 1; private bool continueCalculating = false; public Window1() : base() { InitializeComponent(); } public void StartOrStop(object sender, EventArgs e) { if (continueCalculating) { continueCalculating = false; startStopButton.Content = "Resume"; } else { continueCalculating = true; startStopButton.Content = "Stop"; startStopButton.Dispatcher.BeginInvoke(DispatcherPriority.Normal,new NextPrimeDelegate(CheckNextNumber)); } } public void CheckNextNumber() { numberTextBlock.Text = num.ToString(); num += 2; if (continueCalculating) { startStopButton.Dispatcher.BeginInvoke( System.Windows.Threading.DispatcherPriority.SystemIdle, new NextPrimeDelegate(this.CheckNextNumber)); } } } }
BlockThread.xaml
<Window x:Class="WPFThreading.BlockThread" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="UI Thread Blocker" Height="275" Width="225" > <Window.Resources> <Style TargetType="{x:Type Button}"> <Setter Property="Height" Value="20" /> <Setter Property="Background" Value="Beige"/> <Setter Property="Margin" Value="2" /> </Style> <Style TargetType="{x:Type Label}"> <Setter Property="FontWeight" Value="Bold" /> <Setter Property="Margin" Value="2" /> </Style> <Style TargetType="{x:Type TextBox}"> <Setter Property="Margin" Value="2" /> </Style> </Window.Resources> <Border Width="200" Height="225" BorderBrush="Black" BorderThickness="1" Margin="4"> <StackPanel> <Label>Simulate Long-Running Process</Label> <Button Name="button1" Click="button1_click">Go to sleep</Button> <Label>Will I respond?</Label> <Button Name="button2" Click="button2_click">Try Me</Button> <Label>Output Messages</Label> <TextBox Name="textbox1"/> <Label/> <StackPanel Orientation="Horizontal"> <Label>UI thread:</Label> <Label Name="UIThreadLabel"></Label> </StackPanel> <StackPanel Orientation="Horizontal"> <Label>BG thread:</Label> <Label Name="BackgroundThreadLabel"></Label> </StackPanel> </StackPanel> </Border> </Window> //File:Window.xaml.cs using System.Windows; namespace WPFThreading { public partial class BlockThread : System.Windows.Window { public BlockThread() { InitializeComponent(); this.UIThreadLabel.Content = this.Dispatcher.Thread.ManagedThreadId; this.BackgroundThreadLabel.Content = "N/A"; } private void button1_click(object sender, RoutedEventArgs e) { System.Threading.Thread.Sleep(5000); this.textbox1.Text = "Done Sleeping..."; } private void button2_click(object sender, RoutedEventArgs e) { this.textbox1.Text = "Hello WPF"; } } }
ThreadPool.QueueUserWorkItem
<Window x:Class="DispatcherExamples.MyWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Use BeginInvoke" Height="300" Width="300" > <Grid> <StackPanel> <Button x:Name="useBeginInvokeButton" Content="Use BeginInvoke" /> </StackPanel> </Grid> </Window> //File:Window.xaml.cs using System; using System.Collections.Generic; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; using System.Windows.Threading; using System.Threading; namespace DispatcherExamples { public partial class MyWindow : System.Windows.Window { public MyWindow() { InitializeComponent(); useBeginInvokeButton.Click += new RoutedEventHandler(useBeginInvokeButton_Click); } void useBeginInvokeButton_Click(object sender, RoutedEventArgs e) { ThreadPool.QueueUserWorkItem(delegate { MyDelegateType methodForUiThread = delegate { this.Background = new SolidColorBrush(Color.FromRgb(3,2, 1)); }; this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, methodForUiThread); }); } public delegate void MyDelegateType(); } }
Execute a Method Asynchronously Using the Dispatcher Queue
<Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="WPF" Width="220" Height="104" > <StackPanel Orientation="Vertical"> <Button Click="StartStop_Click" Name="btnStartStop">Start</Button> <StackPanel Orientation="Horizontal"> <TextBlock>Biggest Prime Found:</TextBlock> <TextBlock Name="txtNumber"/> </StackPanel> </StackPanel> </Window> //File:Window.xaml.cs using System; using System.Windows; using System.Windows.Threading; namespace WpfApplication1 { public partial class Window1 : Window { private bool continueCalculating = false; public Window1() : base() { InitializeComponent(); } private void StartStop_Click(object sender, RoutedEventArgs e) { if(continueCalculating) { continueCalculating = false; btnStartStop.Content = "Start"; } else { continueCalculating = true; btnStartStop.Content = "Stop"; this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,new Action<int>(UpdateNumber), 3); } } public void UpdateNumber(int current) { txtNumber.Text = current.ToString(); if(continueCalculating) { this.Dispatcher.BeginInvoke(DispatcherPriority.SystemIdle,new Action<int>(UpdateNumber), current + 2); } } } }
Ensure That You Are Running on the UI Thread
<Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="WPF" Height="100" Width="300"> <StackPanel> <Button Click="ButtonTrue_Click">UI Thread</Button> <Button Click="ButtonFalse_Click">Non-UI Thread</Button> </StackPanel> </Window> //File:Window.xaml.cs using System.Windows; namespace WpfApplication1 { public partial class Window1 : Window { public Window1() { InitializeComponent(); } private void ButtonTrue_Click(object sender, RoutedEventArgs e) { this.Dispatcher.VerifyAccess(); } private void ButtonFalse_Click(object sender, RoutedEventArgs e) { VerifyAccessDelegate del = new VerifyAccessDelegate(VerifyAccess); del.BeginInvoke(null, null); } private delegate void VerifyAccessDelegate(); private void VerifyAccess() { this.Dispatcher.VerifyAccess(); } } }
Check Whether You Are Running on the UI Thread
<Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="WPF" Height="120" Width="364"> <StackPanel> <Button Click="ButtonTrue_Click">UI Thread</Button> <Button Click="ButtonFalse_Click">Non-UI Thread</Button> <TextBlock x:Name="txtResult"/> </StackPanel> </Window> //File:Window.xaml.cs using System.Windows; using System.Windows.Threading; namespace WpfApplication1 { public partial class Window1 : Window { private delegate void CheckAccessDelegate(); private delegate void SetResultTextDelegate(string result); public Window1() { InitializeComponent(); } private void ButtonTrue_Click(object sender, RoutedEventArgs e) { CheckAccess(); } private void ButtonFalse_Click(object sender, RoutedEventArgs e) { CheckAccessDelegate del = new CheckAccessDelegate(CheckAccess); del.BeginInvoke(null, null); } private void CheckAccess() { if(txtResult.Dispatcher.CheckAccess()) { txtResult.Text = "True"; }else{ txtResult.Dispatcher.BeginInvoke(DispatcherPriority.Normal,new SetResultTextDelegate(SetResultText),"False"); } } private void SetResultText(string result) { txtResult.Text = result; } } }