现在的位置: 首页 > 综合 > 正文

WPF – 简单异步模式

2012年03月25日 ⁄ 综合 ⁄ 共 2754字 ⁄ 字号 评论关闭

以WeatherForecast为例. 需求: 用户在窗体上点击一个按钮, 程序去网络上查询天气情况, 并把结果显示在窗体上. 网络查询是一个耗时任务, 在等待结果的同时, 用户将看到一个旋转的时钟动画表示程序正在查询.

 

模式为:

  1. 窗口类MainWindow中有耗时函数: string FetchWeatherFromInternet().
  2. 窗口类MainWindow中包含一个函数 UpdateUIWhenWeatherFetched(string result), 用于把任务结果显示在界面上.
  3. 当用户点击按钮时, 在 btnFetchWeather_Click() 中,

    如果是同步调用, 代码很简单, 如下:
    string result = this.FetchWeatherFromInternet();
    this.UpdateUserInterface( result );

    现在需要异步执行, 稍微麻烦点, 需要用到3个delegate, 其中一个代表要执行的任务, 另一个代表任务结束后的callback, 还有一个代表交给UI执行的任务, 上述代码被替换成如下:

    // 代表要执行的异步任务
    Func<string> asyncAction = this.FetchWeatherFromInternet();

    // 处理异步任务的结果
    Action<IAsyncResult> resultHandler = delegate( IAsyncResult asyncResult )
    {
             //获得异步任务的返回值, 这段代码必须在UI线程中执行
             string weather = asyncAction.EndInvoke( asyncResult );
             this.UpdateUIWhenWeatherFetched( weather );
    };

    //代表异步任务完成后的callback
    AsyncCallback asyncActionCallback = delegate( IAsyncResult asyncResult )
    {
            this.Dispatcher.BeginInvoke( DispatcherPriority.Background, resultHandler, asyncResult );
    };

    //这是才开始执行异步任务
    asyncAction.BeginInvoke( asyncActionCallback, null );

=======================================================================

private void ForecastButtonHandler(object sender, RoutedEventArgs e)
{
    this.UpdateUIWhenStartFetchingWeather();

    //异步任务封装在一个delegate中, 此delegate将运行在后台线程 
    Func<string> asyncAction = this.FetchWeatherFromInternet;
 
    //在UI线程中得到异步任务的返回值,并更新UI
//必须在UI线程中执行

Action<IAsyncResult> resultHandler = delegate(IAsyncResult asyncResult)
{
string weather = asyncAction.EndInvoke(asyncResult);
this.UpdateUIWhenWeatherFetched(weather);
};
 
    //异步任务执行完毕后的callback, 此callback运行在后台线程上. 
//此callback会异步调用resultHandler来处理异步任务的返回值.
AsyncCallback asyncActionCallback = delegate(IAsyncResult asyncResult) { this.Dispatcher.BeginInvoke(DispatcherPriority.Background, resultHandler, asyncResult); }; //在UI线程中开始异步任务,
//asyncAction(后台线程), asyncActionCallback(后台线程)和resultHandler(UI线程)
//将被依次执行
asyncAction.BeginInvoke(asyncActionCallback, null); } private string FetchWeatherFromInternet() { // Simulate the delay from network access. Thread.Sleep(4000); String weather = "rainy"; return weather; } private void UpdateUIWhenStartFetchingWeather() { // Change the status
this.fetchButton.IsEnabled = false; this.weatherText.Text = ""; } private void UpdateUIWhenWeatherFetched(string weather) { //Update UI text this.fetchButton.IsEnabled = true; this.weatherText.Text = weather; }

抱歉!评论已关闭.