源项目地址:https://github.com/Microsoft/...
如下是把样例转换为简要说明,同时给出实际运行效果及关键代码:git
private void Browse(object sender, RoutedEventArgs e) { placeHolder.Source = new Uri(newLocation.Text); } private void NewWindowHandler(object sender, RoutedEventArgs e) { var newWindowThread = new Thread(ThreadStartingPoint); newWindowThread.SetApartmentState(ApartmentState.STA); newWindowThread.IsBackground = true; newWindowThread.Start(); } private void ThreadStartingPoint() { var tempWindow = new MainWindow(); tempWindow.Show(); Dispatcher.Run(); //Dispatcher.BeginInvoke(DispatcherPriority.Normal, //(ThreadStart)delegate () //{ // var temWindow = new MainWindow(); // temWindow.Show(); //}); }
调用自身线程循环查找素数 private 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() { Stopwatch x = new Stopwatch(); x.Start(); // Reset flag. _notAPrime = false; for (long i = 3; i <= Math.Sqrt(_num); i++) { if (_num%i == 0) { // Set not a prime flag to ture. _notAPrime = true; break; } } // If a prime number. if (!_notAPrime) { x.Stop(); elapsed.Text = x.ElapsedTicks.ToString(); bigPrime.Text = _num.ToString(); } _num += 2; if (_continueCalculating) { startStopButton.Dispatcher.BeginInvoke( DispatcherPriority.SystemIdle, new NextPrimeDelegate(CheckNextNumber)); } }
在本示例中,模拟检索天气预报的远程过程调用。 使用一个单独的辅助线程来执行此调用,并在完成后在 UI 线程的 Dispatcher 中调度一个更新方法。github
private void ForecastButtonHandler(object sender, RoutedEventArgs e) { // Change the status image and start the rotation animation. fetchButton.IsEnabled = false; fetchButton.Content = "Contacting Server"; weatherText.Text = ""; _hideWeatherImageStoryboard.Begin(this); // Start fetching the weather forecast asynchronously. var fetcher = new NoArgDelegate( FetchWeatherFromServer); fetcher.BeginInvoke(null, null); }
当单击按钮时,显示时钟图并开始显示它的动画效果。 禁用该按钮, 在一个新线程中调用 FetchWeatherFromServer 方法,而后返回,这样 Dispatcher 就能够在咱们等待收集天气预报时处理事件。网络
private void FetchWeatherFromServer() { // Simulate the delay from network access. Thread.Sleep(4000); // Tried and true method for weather forecasting - random numbers. var rand = new Random(); string weather; weather = rand.Next(2) == 0 ? "rainy" : "sunny"; // Schedule the update function in the UI thread. tomorrowsWeather.Dispatcher.BeginInvoke( DispatcherPriority.Normal, new OneArgDelegate(UpdateUserInterface), weather); }
为简单起见,此示例中实际没有任何网络代码。 经过使新线程休眠四秒钟来模拟网络访问的延迟。 此时,原始的 UI 线程仍然正在运行并响应事件。为了对此进行说明,咱们使一个动画保持运行,并使最小化和最大化按钮也继续工做。框架
当延迟结束,而且咱们已随机选择了天气预报时,是时候向 UI 线程返回报告了。为此,咱们在 UI 线程中使用该线程的 Dispatcher 安排一个对 UpdateUserInterface 的调用。咱们将一个描述天气的字符串传递给安排的此方法调用。dom
private void UpdateUserInterface(string weather) { //Set the weather image if (weather == "sunny") { weatherIndicatorImage.Source = (ImageSource) Resources[ "SunnyImageSource"]; } else if (weather == "rainy") { weatherIndicatorImage.Source = (ImageSource) Resources[ "RainingImageSource"]; } //Stop clock animation _showClockFaceStoryboard.Stop(this); _hideClockFaceStoryboard.Begin(this); //Update UI text fetchButton.IsEnabled = true; fetchButton.Content = "Fetch Forecast"; weatherText.Text = weather; }
当 UI 线程中的 Dispatcher 有时间时,会对 UpdateUserInterface 执行预约调用。此方法中止时钟动画并选择一个图像来描述天气。它显示此图像并还原“fetch forecast”(获取预报)按钮。异步
以上。async
《Microsoft .NET Framework 开发人员指南》介绍了组件向其客户端公开异步行为的一种模式(请参见 基于事件的异步模式概述)。例如,假定咱们但愿将 FetchWeatherFromServer 方法打包到一个可重用的非图形组件中。若是采用标准的 Microsoft .NET Framework 模式,那么代码应与下面的内容相似。ide
public class WeatherComponent : Component { //gets weather: Asynchronous public string GetWeather() { string weather = ""; //predict the weather return weather; } //get weather: Asynchronous public void GetWeatherAsync() { //get the weather } public event GetWeatherCompletedEventHandler GetWeatherCompleted; } public class GetWeatherCompletedEventArgs : AsyncCompletedEventArgs { public GetWeatherCompletedEventArgs(Exception error, bool canceled, object userState, string weather) : base(error, canceled, userState) { _weather = weather; } public string Weather { get { return _weather; } } private string _weather; } public delegate void GetWeatherCompletedEventHandler(object sender, GetWeatherCompletedEventArgs e);
GetWeatherAsync 将使用前面介绍的一种技术(如建立后台线程)来异步执行工做,同时不阻止调用线程。fetch
此模式的最重要部分之一是最初在调用方法名称 Async 方法的线程上调用方法名称 Completed 方法。 经过存储 CurrentDispatcher,您可使用 WPF 轻松地实现这一点。可是,以后只能在 WPF应用程序中使用该非图形组件,而不能在 Windows Forms或 ASP.NET 程序中使用该组件。动画
DispatcherSynchronizationContext 类可知足这一需求。能够将该类视为还使用其余 UI 框架的 Dispatcher 的简化版本。
public class WeatherComponent2 : Component { public string GetWeather() { return fetchWeatherFromServer(); } private DispatcherSynchronizationContext requestingContext = null; public void GetWeatherAsync() { if (requestingContext != null) throw new InvalidOperationException("This component can only handle 1 async request at a time"); requestingContext = (DispatcherSynchronizationContext)DispatcherSynchronizationContext.Current; NoArgDelegate fetcher = new NoArgDelegate(this.fetchWeatherFromServer); // Launch thread fetcher.BeginInvoke(null, null); } private void RaiseEvent(GetWeatherCompletedEventArgs e) { if (GetWeatherCompleted != null) GetWeatherCompleted(this, e); } private string fetchWeatherFromServer() { // do stuff string weather = ""; GetWeatherCompletedEventArgs e = new GetWeatherCompletedEventArgs(null, false, null, weather); SendOrPostCallback callback = new SendOrPostCallback(DoEvent); requestingContext.Post(callback, e); requestingContext = null; return e.Weather; } private void DoEvent(object e) { //do stuff } public event GetWeatherCompletedEventHandler GetWeatherCompleted; public delegate string NoArgDelegate(); }
此处在MSDN或Microsoft Help查看器中WPF线程处理模型说起。