• WPF 简单异步模式


    以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; }
  • 相关阅读:
    CentOS7安装redis
    apache修改最大连接数报错
    阿里云服务器安全组设置
    CentOS7为firewalld添加开放端口
    php程序报错:PHP Core Warning/cannot open shared object file: No such file or directory
    centos7配置Apache支持HTTPS
    linux系统下Apache日志分割(按天生成文件)
    springboot 项目依赖 es包版本异常
    jboss Marshalling, 服务端收不到消息
    gateway 整合 websocket demo
  • 原文地址:https://www.cnblogs.com/mrfangzheng/p/1390115.html
Copyright © 2020-2023  润新知