异步编程

1async/await特性结构
异步方法:就是在处理完成之前就返回到调用方法。
async/await特性结构由三个部分构成:
(1)调用方法:调用异步方法的那个方法,它和异步方法可能在相同的线程,也可能在不同的线程。在异步方法执行其任务的时候继续执行。
class Program
{
    static void Main()
     {
        ……
        Task<int> value=DoAsyncStuff.CalculateSumAsync(5,6);
         ……
       }
}
(2) 异步方法:有异步标识 async
static class DoAsyncStuff
{ 
     public static async Task<int>  CalculateSumAsync(int i1,int i2) ----这就是异步方法 有异步标识 async
     {
          int sum=await TaskEx.Run( () => GetSum(i1,i2));
          return sum;
      }
       ……
}
(3) await 表达式:异步方法内部,指明需要异步执行的任务。一个异步方法至少包含一个await表达式。
2 什么是异步方法
(1)异步方法
async关键字
至少一个await表达式
返回类型:void  Task  Task<T>
参数不能为out或ref参数
除了方法以外,Lambda表达式和匿名方法也可以作为异步对象。
Task<T>: 如果调用方法要获取一个T类型的值,异步方法的返回类型就必须是Task<T>.调用方法将通过读取Task的Result属性来获取这个T类型的值。这个是有返回参数的返回类型 例如:
Task<int> value=DoStuff.CalculateSumAsync(5,6);
……
Console.WriteLine("Value : {0}",value.Result);
Task: 如果调用方法不需要从异步方法中返回某个值,但需要检查异步方法的状态,那么异步方法可以返回一个Task类型的对象。这时,即使异步方法出现了return语句,也不返回任何东西。例如:
Task  someTask=DoStuff.CalculateSumAsync(5,6);
……
somTask.Wait();
Void:如果调用方法仅仅想执行异步方法,而不需要与它做任何进一步的交互时[这成为[fire and forget]。这时,与上面一样,即使方法中包含return语句也不会返回任何东西。

Demo:使用返回Task<int> 对象的异步方法
 classProgram
 {
     staticvoid Main(string[] args)
     {
        Task<int> value=DoAsyncStuff.CalculateSumAsync(5,6);
        Console.WriteLine("Value:{0}", value.Result);
      }
  }
  static async Task<int> CalculateSumAsync(int i1, int i2)
  {
      int sum = awaitTask.Run(() => GetSum(i1, i2));
      return sum;
  } 
 privatestaticint GetSum(int i1, int i2)
 {
    return i1 + i2;
 }
Demo:使用返回Task对象的异步方法

 classProgram
    {
        staticvoid Main(string[] args)
        {
            Task someTask = DoAsyncStuff.CalculateSumAsync1(5, 6);
            //处理其他事情
            someTask.Wait();
            Console.WriteLine("Async stuff is done");
            Console.ReadLine();
        }
    }  
publicstaticasyncTask CalculateSumAsync1(int i1, int i2)
   {
       int sum = awaitTask.Run(() => GetSum(i1, i2));
       Console.WriteLine("Value:{0}", sum);
    }
 privatestaticint GetSum(int i1, int i2)
 { return i1 + i2;}
Demo:使用返回void的异步方法
  staticvoid Main(string[] args)
        {
            DoAsyncStuff.CalculateSumAsync2(5, 6);
            //处理其他事情
            Thread.Sleep(200);----如果这里不暂停当前线程,则会先输出Program Exiting,在输出11
            Console.WriteLine("Program Exiting");
        }
  publicstaticasyncvoid CalculateSumAsync2(int i1, int i2)
        {
            int sum = awaitTask.Run(() => GetSum(i1, i2));
            Console.WriteLine("Value:{0}", sum);
        } 
        privatestaticint GetSum(int i1, int i2)
        {return i1 + i2; }

当程序运行到异步方法内部的await表达式时,异步方法会立即创建一个返回类型Task或Task<T>的对象,并返回给调用方法。
调用方法使用Task对象,取其Result属性时,如果异步方法还没有设置该属性,调用方法就暂停等待。

(2)异步方法控制流:




     privateasyncTask<int> CountCharactersAsync(string uriString)
        {
            WebClient wc = newWebClient();
            string result = await wc.DownloadStringTaskAsync(uriString);
            return result.Length;
        }
上面的异步方法,在遇到await时会立即返回,返回的这个类型与await表达式本身的内容没有关系,会创建一个异步方法返回类型的对象,即Task<int>对象。而异步方法的return语句并没有真正返回某个值,只是退出了。
(3)await表达式
.net 4.5,有大量的异步方法在BCL中。比如上面的DownloadStringTaskAsync方法等。
也可以自己编写异步方法:
使用Task.Run()方法,这个方法是在不同的线程上运行你的方法。
Task.Run的签名:Task Run(Func<TReturn> func)
因此定义异步方法,最重要的就是要创建一个委托。
Demo:使用Task.Run定义await表达式,进而定义异步方法。
 classMyClass
    {
        publicint Get10()
        { return 10; }
        publicasyncTask DoWorkAsync()
        {
            Func<int> ten = newFunc<int>(Get10);
            int a = awaitTask.Run(ten);
            int b = awaitTask.Run(newFunc<int>(Get10));
            int c = awaitTask.Run(() => { return 10; });//该Lambda表达式是与Func<int>兼容的将隐式转换为该委托
            Console.WriteLine("{0}  {1} {2}", a, b, c);
        }
    }
   staticvoid Main(string[] args)
        {
            Task t = (newMyClass()).DoWorkAsync();
            Console.WriteLine("111");
            t.Wait();
            Console.WriteLine("222");
        }
结果:

Task.Run:



4)取消一个异步操作 5)异常处理与await表达式 Task t t.Satus t.IsFaulted (6)在调用方法中同步的等待任务 wait() t.Wait(); Task.WaitAll(); Task.WaitAny(); (7)在异步方法中异步的等待任务 异步等待所有tasks中的任务完成,不会占用主线程的时间。
原文地址:https://www.cnblogs.com/rwh871212/p/6963370.html