C#编程总结(六)详解异步编程

2019-12-30 14:38:08丽君

测试用例


using System;
using System.Threading;

namespace AsynSample
{
  class Program
  {
    static void Main(string[] args)
    {
      FileReader reader = new FileReader(1024);

      //改为自己的文件路径
      string path = "C:WindowsDAI.log";

      Console.WriteLine("开始读取文件了...");
      //reader.SynsReadFile(path);

      reader.AsynReadFile(path);

      Console.WriteLine("我这里还有一大滩事呢.");
      DoSomething();
      Console.WriteLine("终于完事了,输入任意键,歇着!");
      Console.ReadKey();      
    }
    /// <summary>
    /// 
    /// </summary>
    static void DoSomething()
    {
      Thread.Sleep(1000);
      for (int i = 0; i < 10000; i++)
      {
        if (i % 888 == 0)
        {
          Console.WriteLine("888的倍数:{0}",i);
        }
      }
    }
  }
}

输出结果:

同步输出:

c#,异步编程,异步编程详解

异步输出:

c#,异步编程,异步编程详解

结果分析:

如果是同步读取,在读取时,当前线程读取文件,只能等到读取完毕,才能执行以下的操作

而异步读取,是创建了新的线程,读取文件,而主线程,继续执行。我们可以开启任务管理器来进行监视。

案例二--基于委托的异步操作

系统自带一些类具有异步调用方式,如何使得自定义对象也具有异步功能呢?

我们可以借助委托来轻松实现异步。

说到BeginInvoke,EndInvoke就不得不停下来看一下委托的本质。为了便于理解委托,我定义一个简单的委托:


public delegate string MyFunc(int num, DateTime dt);

我们再来看一下这个委托在编译后的程序集中是个什么样的:c#,异步编程,异步编程详解

委托被编译成一个新的类型,拥有BeginInvoke,EndInvoke,Invoke这三个方法。前二个方法的组合使用便可实现异步调用。第三个方法将以同步的方式调用。 其中BeginInvoke方法的最后二个参数用于回调,其它参数则与委托的包装方法的输入参数是匹配的。 EndInvoke的返回值与委托的包装方法的返回值匹配。

异步实现文件下载:


using System;
using System.Text;

namespace AsynSample
{
  /// <summary>
  /// 下载委托
  /// </summary>
  /// <param name="fileName"></param>
  public delegate string AysnDownloadDelegate(string fileName);
  /// <summary>
  /// 通过委托实现异步调用
  /// </summary>
  class DownloadFile
  {
    /// <summary>
    /// 同步下载
    /// </summary>
    /// <param name="fileName"></param>
    public string Downloading(string fileName)
    {
      string filestr = string.Empty;
      Console.WriteLine("下载事件开始执行");
      System.Threading.Thread.Sleep(3000);
      Random rand = new Random();
      StringBuilder builder =new StringBuilder();
      int num;
      for(int i=0;i<100;i++)
      {
        num = rand.Next(1000);
        builder.Append(i);
      }
      filestr = builder.ToString();
      Console.WriteLine("下载事件执行结束");

      return filestr;
    }
    /// <summary>
    /// 异步下载
    /// </summary>
    public IAsyncResult BeginDownloading(string fileName)
    {
      string fileStr = string.Empty;
      AysnDownloadDelegate downloadDelegate = new AysnDownloadDelegate(Downloading);
      return downloadDelegate.BeginInvoke(fileName, Downloaded, downloadDelegate);
    }
    /// <summary>
    /// 异步下载完成后事件
    /// </summary>
    /// <param name="result"></param>
    private void Downloaded(IAsyncResult result)
    {
      AysnDownloadDelegate aysnDelegate = result.AsyncState as AysnDownloadDelegate;
      if (aysnDelegate != null)
      {
        string fileStr = aysnDelegate.EndInvoke(result);
        if (!string.IsNullOrEmpty(fileStr))
        {
          Console.WriteLine("下载文件:{0}", fileStr);
        }
        else
        {
          Console.WriteLine("下载数据为空!");
        }
      }
      else
      {
        Console.WriteLine("下载数据为空!");
      }
    }
  }
}