• C#多线程之异步编程


       c#中异步编程,主要有两种方法: 1、委托的异步调用; 2、Task的await,async (c# 4.5)

     我们来看例子:

    1         /// <summary>
    2         /// 异步保存网页,url:网页地址,path:要保存的位置
    3         /// </summary>
    4         private void SavePageAsync(string url, string path)
    5         {
    6             Func<string, string, bool> fun = SavePageSingleFile;
    7             IAsyncResult result = fun.BeginInvoke(url, path, new AsyncCallback(SavePageCompleted), null);
    8         }

    Func,是系统定义好的委托类型,当然也可以自定义委托了,委托的本质是一个类,它有一个BeginInvoke 异步调用方法。SavePageSingleFile方法是委托要执行的方法:

     1         private bool SavePageSingleFile(string url, string path)
     2         {
     3             bool result = false;
     4             try
     5             {
     6                 CDO.Message message = new CDO.MessageClass();
     7                 ADODB.Stream stream = null;
     8                 message.MimeFormatted = true;
     9                 message.CreateMHTMLBody(url, CDO.CdoMHTMLFlags.cdoSuppressNone, "", "");
    10                 stream = message.GetStream();
    11                 stream.SaveToFile(path, ADODB.SaveOptionsEnum.adSaveCreateOverWrite);
    12                 message = null;
    13                 stream.Close();
    14 
    15                 result = true;
    16             }
    17             catch (Exception ex)
    18             {
    19                 Logger.Debug("保存文件出错:" + ex.Message);
    20             }
    21             return result;
    22         }
      
    委托任务完成后的回调方法 SavePageCompleted:
     1       private void SavePageCompleted(IAsyncResult result)
     2        {
     3             try
     4             {
     5                 var handler = (Func<string, string, bool>)((AsyncResult)result).AsyncDelegate;
     6                 var r = handler.EndInvoke(result);
     7 
     8                 this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
     9                                    (ThreadStart)delegate()
    10                                    {
    11                                        this.Opacity = 1;
    12 
    13                                        if (CloseWaittingWindow != null)
    14                                        {
    15                                            CloseWaittingWindow();
    16                                        }
    17                                        this.Cursor = System.Windows.Input.Cursors.Hand;
    18 
    19                                        MessageTip tip = new MessageTip();
    20                                        if (r)
    21                                        {
    22                                            tip.Show("保存网页", "文件保存成功");
    23                                        }
    24                                        else
    25                                        {
    26                                            tip.Show("保存网页", "文件保存失败");
    27                                        }
    28                                    }
    29                           );
    30             }
    31             catch (Exception ex)
    32             {
    33                 Logger.Debug("保存页面文件出错:" + ex.Message);
    34                 this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
    35                                  (ThreadStart)delegate()
    36                                  {
    37                                      new MessageTip().Show("保存网页", "文件保存出错");
    38                                      this.Opacity = 1;
    39 
    40                                      if (CloseWaittingWindow != null)
    41                                      {
    42                                          CloseWaittingWindow();
    43                                      }
    44                                      this.Cursor = System.Windows.Input.Cursors.Hand;
    45                                  }
    46                         );
    47             }
    48         }

    最后看下 SavePageAsync 方法的调用:

     1         /// <summary>
     2         /// 保存当前页面
     3         /// </summary>
     4         /// <param name="sender"></param>
     5         /// <param name="e"></param>
     6         private void btnSavePage_Click(object sender, RoutedEventArgs e)
     7         {
     8             if (this.DBVisitViewModel.CanSavePageExcute)
     9             {
    10                 string url = this.WebPageBrower.Url.AbsoluteUri;
    11                 if (!Tool.CheckUrl(url))
    12                 {
    13                     new MessageTip().Show("保存页面", "当前页面无法保存");
    14                     return;
    15                 }
    16 
    17                 SaveFileDialog sfd = new SaveFileDialog();
    18 
    19                 sfd.InitialDirectory = @"D:";
    20                 sfd.Filter = "mht file|*.mht";
    21 
    22                 if (sfd.ShowDialog() == DialogResult.OK)
    23                 {
    24                     if (OpenWaittingWindow != null)
    25                     {
    26                         this.Cursor = System.Windows.Input.Cursors.Wait;
    27                         SavePageAsync(url, sfd.FileName);
    28 
    29                         this.Opacity = 0.8;
    30                         OpenWaittingWindow("正在保存网页,请稍等...");
    31                     }
    32                 }
    33             }
    34         }

    在framework 4.0的时候,委托异步调用显得很方便,到了4.5的时候,我们可以用Task实现异步调用。改下上面的例子:

     1        private async void SavePageAsync(string url, string path)
     2         {
     3             var r = await SavePageSingleFile(url, path);
     4 
     5             try
     6             {
     7                 this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
     8                                    (ThreadStart)delegate()
     9                                    {
    10                                        this.Opacity = 1;
    11 
    12                                        if (CloseWaittingWindow != null)
    13                                        {
    14                                            CloseWaittingWindow();
    15                                        }
    16                                        this.Cursor = System.Windows.Input.Cursors.Hand;
    17 
    18                                        MessageTip tip = new MessageTip();
    19                                        if (r)
    20                                        {
    21                                            tip.Show("保存网页", "文件保存成功");
    22                                        }
    23                                        else
    24                                        {
    25                                            tip.Show("保存网页", "文件保存失败");
    26                                        }
    27                                    }
    28                           );
    29             }
    30             catch (Exception ex)
    31             {
    32                 Logger.Debug("保存页面文件出错:" + ex.Message);
    33                 this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
    34                                  (ThreadStart)delegate()
    35                                  {
    36                                      new MessageTip().Show("保存网页", "文件保存出错");
    37                                      this.Opacity = 1;
    38 
    39                                      if (CloseWaittingWindow != null)
    40                                      {
    41                                          CloseWaittingWindow();
    42                                      }
    43                                      this.Cursor = System.Windows.Input.Cursors.Hand;
    44                                  }
    45                         );
    46             }
    47 
    48 
    49 
    50         }
    51         static async Task<bool> SavePageSingleFile(string url, string path)
    52         {
    53             return await Task.Run(() =>
    54             {
    55                 bool result = false;
    56                 try
    57                 {
    58                     CDO.Message message = new CDO.MessageClass();
    59                     ADODB.Stream stream = null;
    60                     message.MimeFormatted = true;
    61                     message.CreateMHTMLBody(url, CDO.CdoMHTMLFlags.cdoSuppressNone, "", "");
    62                     stream = message.GetStream();
    63                     stream.SaveToFile(path, ADODB.SaveOptionsEnum.adSaveCreateOverWrite);
    64                     message = null;
    65                     stream.Close();
    66 
    67                     result = true;
    68                 }
    69                 catch (Exception ex)
    70                 {
    71                     Logger.Debug("保存文件出错:" + ex.Message);
    72                 }
    73                 return result;
    74             });
    75         }

    第5行后的try,catch语句块,就是保存网页后的回调,它的执行是在子线程中,因此,在wpf 中要用 Dispatcher(回调中牵扯到对页面的操作)。为了简化这一例子,我这儿给出一个简单的可以执行的例子:

     1   static void Main(string[] args)
     2         {
     3             Add(2,3);
     4             Console.WriteLine("主线程:" + Thread.CurrentThread.ManagedThreadId);
     5             Console.WriteLine("main Thread go on sth"); 
     6             Console.Read();
     7         }
     8 
     9         private async static void Add(int x, int y)
    10         {
    11             Console.WriteLine("主线程:" + Thread.CurrentThread.ManagedThreadId);
    12             var t = await TestAsync(x,y);
    13             Console.WriteLine("正在等待完成任务,当前线程:"+Thread.CurrentThread.ManagedThreadId);
    14 
    15             Console.WriteLine("运行结果:" + t);                      
    16         }
    17         static async Task<int> TestAsync(int x, int y)
    18         {
    19             return await Task.Run(() =>
    20             {
    21                 Thread.Sleep(1000);
    22                 Console.WriteLine("子线程:" + Thread.CurrentThread.ManagedThreadId);
    23                 return x + y;                         
    24             });
    25         }

    运行结果:

    异步编程主要是为了解决耗时的任务占用主线程的问题,比如ajax的异步调用,不会导致页面卡死。好了,今天就谈到这里,该吃中午饭了。

  • 相关阅读:
    原型设计工具 SketchFlow
    Vs2010架构设计层图(Layer Diagram)
    javascript in Visual Studio
    COM应用总结补充【COM+】
    WMI介绍、WQL
    Windows Azure Platform AppFabric 3/3
    Windows脚本 实例 3/4
    Silverlight Training
    一个很好的sliverlight站点
    建模形式构建Zend Framework应用
  • 原文地址:https://www.cnblogs.com/wangqiang3311/p/7813829.html
Copyright © 2020-2023  润新知