根据代码示例来学习,编程
建立一个函数来模拟时间消耗的方法,此处为GetSomeThing
函数。并发
要使用异步编程,须要使用一个async修饰的方法来包装调用GetSomeThing
函数,此函数的返回值为Task类型,该类型表示进行并行运算的任务引用。此处示例为ConsumeManyTime
函数。dom
TestOne()
函数中的代码,其实就是直接调用第二步中的函数ConsumeManyTime()
;总结:
异步编程虽然示例三步,可是实际上就是两步的事情,第一步是模拟应用,跟异步编程自己没有关系,第二步包装一个Task返回类型的async
修饰的方法,该方法实际调用应用函数,第三步调用第二步的方法,从而执行对模拟应用的异步执行。异步
附加:
除了异步编程之外,C#还提供了并发编程相关功能,极大简化了并发任务的开发,能够让开发人员无需建立线程池以及管理线程这些工做,就能够直接使用并发开发带来的优点。 示例代码见Testpallral()
。async
代码以下ide
class Program { static int i = 0; //模拟耗时的运算或者IO public static bool GetSomeThing(string a) { Thread.Sleep((new Random()).Next()%10*1000); i++; Console.WriteLine(DateTime.Now.ToLongTimeString()+"5-" + Thread.GetCurrentProcessorId().ToString()); return true; } //生成一个task类型,其中包装调用GetSomeThing public static Task<bool> GetSomeThingAsync(string a) { return Task.Run<bool>(()=> { return GetSomeThing(a); } ); }
//方式1:包装给调用方使用的方法,使用async修饰,由于里面有await。 调用方执行到await会当即返回,后续的内容再也不直接调用, await以后的方法都会在可能在其余线程中使用, public async static void ConsumeManyTime() { Console.WriteLine(DateTime.Now.ToLongTimeString() + "3-" +Thread.GetCurrentProcessorId().ToString()); bool result = await GetSomeThingAsync("test"); Console.WriteLine(DateTime.Now.ToLongTimeString() + "4-" +Thread.GetCurrentProcessorId().ToString()); } //方式2:这种调用方式是在异步执行完毕后,能够继续执行预约的后续函数,能够理解为一种回调机制。 public static void ContinueTaskWithConsumeManyTime() { Task<bool> t1 = GetSomeThingAsync("test"); t1.ContinueWith(t => { Console.WriteLine("after await finished " + t.Result + " " + Thread.GetCurrentProcessorId().ToString() + " " + i.ToString()); }); } //方式3:多任务等待方式 public static async void TaskWhenConsumeManyTime() { Task<bool> t1 = GetSomeThingAsync("test"); Task<bool> t2 = GetSomeThingAsync("test"); await Task.WhenAll(t1, t2); Console.WriteLine(DateTime.Now.ToLongTimeString() + "6-" + Thread.GetCurrentProcessorId().ToString()); } //async 和await的基本使用 public static void TestOne() { Console.WriteLine(DateTime.Now.ToLongTimeString() + "1-" + Thread.GetCurrentProcessorId().ToString()); ConsumeManyTime(); ConsumeManyTime(); Console.WriteLine(DateTime.Now.ToLongTimeString() + "2-" + Thread.GetCurrentProcessorId().ToString()); Console.WriteLine("继续输入"); while (Console.ReadLine() != "stop") { Console.WriteLine("继续输入"); } } public static void TestWithContinue() { Console.WriteLine(DateTime.Now.ToLongTimeString() + "1-" + Thread.GetCurrentProcessorId().ToString()); ContinueTaskWithConsumeManyTime(); ContinueTaskWithConsumeManyTime(); Console.WriteLine(DateTime.Now.ToLongTimeString() + "2-" + Thread.GetCurrentProcessorId().ToString()); Console.WriteLine("继续输入"); while (Console.ReadLine() != "stop") { Console.WriteLine("继续输入"); } } public static void TestWhen() { Console.WriteLine(DateTime.Now.ToLongTimeString() + "1-" + Thread.GetCurrentProcessorId().ToString()); TaskWhenConsumeManyTime(); Console.WriteLine(DateTime.Now.ToLongTimeString() + "2-" + Thread.GetCurrentProcessorId().ToString()); Console.WriteLine("继续输入"); while (Console.ReadLine() != "stop") { Console.WriteLine("继续输入"); } } public static void Testpallral() { ParallelLoopResult result = Parallel.For(0, 100, async (int i) => { Console.WriteLine(DateTime.Now.ToLongTimeString() + "{0}, task: {1}, thread: {2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId); await Task.Delay(10); Console.WriteLine(DateTime.Now.ToLongTimeString() + "after delay"); }); while (Console.ReadLine() != "stop") { Console.WriteLine("继续输入"); } } public static void Testpallral2() { ParallelLoopResult result = Parallel.For(0, 100,async(int i, ParallelLoopState pls) => { Console.WriteLine(DateTime.Now.ToLongTimeString() + "{0}, task: {1}, thread: {2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId); await Task.Delay(10); if (i > 5) pls.Break(); Console.WriteLine(DateTime.Now.ToLongTimeString() + "after delay"); } ); while (Console.ReadLine() != "stop") { Console.WriteLine("继续输入"); } } static void Main(string[] args) { //TestWhen(); //Testpallral2(); } }