澳门至尊网站-首页

您的位置:澳门至尊网站 > 免费资源 > 异步编制程序

异步编制程序

2019-10-24 02:17

上风度翩翩篇轻巧讲明了 线程和线程池以至上下文切换。创制线程代价高昂,暗中认可每一个线程都要据有多量虚构内部存款和储蓄器1M。更有效的做法使用线程池,重复使用线程。在.NET4.0中引进了TPL任务并行库,你能够在将精力集中于程序要成功的做事,相同的时候最大程度地增长代码的品质。在C#5.0中引进了async 和 await关键字,基于职务的异步情势(TAP),所以精晓Task对前面学习异步操作会轻巧些。 

 IO操作的MDA(Direct memory access)形式:直接访谈内部存款和储蓄器,是意气风发种不通过CPU而从来开展内部存储器数据存款和储蓄的数据调换情势,差不离能够不损耗CPU的财富;
 CL帕杰罗所提供的异步编制程序模型就是充足利用硬件的DMA功用来释放CPU的压力;使用线程池进行田间处理,异步将专门的学业移交给线程池中的有个别专业线程来达成,直到异步完结,异步才会透过回调的法子文告线程池,让CLOdyssey响应异步达成;

职分是包装了以异步形式推行的劳作。当运维一个任务,调节大约马上回去调用者,无论任务要进行微微工作。

它是出新的风度翩翩种情势,它接纳 future 格局或回调(callback)机制,以制止爆发不供给的线程。二个 future(或 promise)类型代表有个别将在成功的操作。在 .NET 中,新版 future 类型有Task 和Task<TResult>。 

创建Task任务

异步编制程序格局------应用委托和线程池实现的形式

APM 异步编程模型,Asynchronous Programming Model            C#1.0

EAP 基于事件的异步编制程序方式,Event-based Asynchronous Pattern  C#2.0

TAP 基于职分的异步编程形式,Task-based Asynchronous Pattern    C#4.0

Asyncawait简化异步编程;职责并行库,Task Parallel Library     C#5

 有两种创设方式

APM

         使用IAsyncResult设计形式的异步操作是透过名叫 BeginXXX 和 EndXXX 的多个点子来完成,这七个主意分别指开头和了结异步操作。该方式允许用更加少的CPU能源(线程)去做越来越多的操作,.NET Framework相当多类也落到实处了该方式,同临时间大家也足以自定义类来促成该情势(也等于在自定义的类中落实重返类型为IAsyncResult接口的BeginXXX方法和担负IAsyncResult包容类型作为唯大器晚成参数的EndXXX方法),别的事委员会托项目也定义了BeginInvoke和EndInvoke方法。举个例子,FileStream类提供BeginRead和EndRead方法来从文件异步读取字节。那三个主意完毕了 Read 方法的异步版本。

调用 BeginXXX 后,应用程序能够三番柒遍在调用线程上试行命令,同不常候异步操作在另三个线程上实施(若是有再次回到值还应调用 EndXXX甘休异步操作,并向该情势传递BeginXXX 方法重临的IAsyncResult对象,得到操作的返回值)。

 图片 1

CompletedSynchronously属性值侧重与提醒信息,而非操作

访谈异步操作的结果,APM提供了三种办法:

1.在调用BeginXXX方法的线程上调用EndXXX方法来获得异步操作的结果;然而这种艺术会卡住调用线程,在领略操作实现之后调用线程手艺继续运维。

2.循环查询IAsyncResult的IsComplete属性,操作完结后再调用EndXXX方法来获得操作重返的结果。

3.IAsyncResult的AsyncWaitHandle属性完结更为灵敏的守候逻辑,调用该属性WaitOne()方法来使叁个线程阻塞并听候操作完毕;再调用EndXXX方法来得到操作的结果。WaitHandle.WaitOne()能够钦命最长的守候时间,如超时重临false;

4. 在调用BeginXXX方法时提供AsyncCallback委托的实例作为参数,在异步操作实现后委托会自动调用(AsyncCallback对象)钦点的法子。(首推办法)AsyncCallback委托仅能够调用相符一定格局的措施(独有一个参数IAsyncResult,且并未有重回值);

图片 2图片 3

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Runtime.Remoting.Messaging;

namespace AsyncCallbackDelegate
{
    public delegate int BinaryOp(int x, int y);
    class Program
    {
        private static bool isDone = false;
        static void Main(string[] args)
        {
            Console.WriteLine("*****  AsyncCallbackDelegate Example *****");
            Console.WriteLine("Main() invoked on thread {0}.",
              Thread.CurrentThread.ManagedThreadId);
            BinaryOp b = new BinaryOp(Add);
            IAsyncResult iftAR = b.BeginInvoke(10, 10,
              new AsyncCallback(AddComplete),
              "Main() thanks you for adding these numbers.");//传入数据
            // Assume other work is performed here...
            while (!isDone)
            {
                Thread.Sleep(1000);
                Console.WriteLine("Working....");
            }
            Console.ReadLine();
        }

        #region Target for AsyncCallback delegate
        // Don't forget to add a 'using' directive for 
        // System.Runtime.Remoting.Messaging!
        static void AddComplete(IAsyncResult itfAR)
        {
            Console.WriteLine("AddComplete() invoked on thread {0}.",
              Thread.CurrentThread.ManagedThreadId);
            Console.WriteLine("Your addition is complete");

            // Now get the result.
            //AsyncCallback委托的目标无法调用其他方法中创建的委托
            //IAsyncResult itfAR 实际上是System.Runtime.Remoting.Messaging命名空间AsyncResult类的一个实例
            AsyncResult ar = (AsyncResult)itfAR;
            //AsyncDelegate静态属性返回原始异步委托引用
            BinaryOp b = (BinaryOp)ar.AsyncDelegate;
            Console.WriteLine("10 + 10 is {0}.", b.EndInvoke(itfAR));

            // Retrieve the informational object and cast it to string.
            //AsyncState属性获取 BeginInvoke第四个参数传入的值
            string msg = (string)itfAR.AsyncState;
            Console.WriteLine(msg);
            isDone = true;
        }

        #endregion

        #region Target for BinaryOp delegate
        static int Add(int x, int y)
        {
            Console.WriteLine("Add() invoked on thread {0}.",
              Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(5000);
            return x + y;
        }
        #endregion
    }
}

AsyncCallback

可怜捕获

在一起实施的主意里面普通管理特别的诀窍是将或者抛出极度的代码放到try...catch...finally里面,之所以能够捕获到,是因为产生非凡的代码与调用的代码位于同三个线程。当调用二个异步方法发生万分时,CL奥迪Q7会捕获况兼在EndXXX方法时再一次将不胜抛出抛出,所以异步调用中的至极在EndXXX方法出捕获就行了。

class ApmExceptionHandling 
{
   public static void Go() 
  {
      WebRequest webRequest = WebRequest.Create("http://0.0.0.0/");
      webRequest.BeginGetResponse(ProcessWebResponse, webRequest);
      Console.ReadLine();
   }
   private static void ProcessWebResponse(IAsyncResult result) {
      WebRequest webRequest = (WebRequest)result.AsyncState;

      WebResponse webResponse = null;
      try {
         webResponse = webRequest.EndGetResponse(result);
         Console.WriteLine("Content length: " + webResponse.ContentLength);
      }
      catch (WebException we) {
         Console.WriteLine(we.GetType() + ": " + we.Message);
      }
      finally {
         if (webResponse != null) webResponse.Close();
      }
   }
}

APM WinForm UI线程回调

鉴于AsyncCallback委托回调是从ThreadPool中的线程实施的,由此对于Winform,若是回调要求操作UI控件,就须要重返到UI线程去,常用的三个点子:

1.  Control类达成了ISynchronizeInvoke接口,提供了Invoke和BeginInvoke方法来扶持任何线程更新GUI分界面控件的体制(将回调方法投递到开创该控件的线程中实行)。

 图片 4

Control类的 Invoke,BeginInvoke 内部得以达成如下:

a) Invoke(同步调用)先剖断控件创造线程与眼下线程是还是不是生龙活虎律,相符则直接调用委托方法;不然使用Win32API的PostMessage异步施行,可是Invoke内部会调用IAsyncResult.AsyncWaitHandle等待施行到位。

b) BeginInvoke(异步调用)使用Win32API的PostMessage 异步施行,而且重临IAsyncResult 对象。

应用方法:回调方法中对控件检查测验InvokeRequired值,if true,在该回调中封送一次委托,调用控件的Invoke/ BeginInvoke方法;

 图片 5

2.GUI(WinForm/WPF)应用程序引进了三个线程管理模型:创立窗口的线程是天下无双能对非凡窗口进行更新的线程;在GUI线程中,平常要求扭转异步操作,使GUI线程不打断并截至响应顾客输入。不过,异步操作实现时,由于是用三个线程池线程完结的,而线程池线程无法更新UI控件。为消除这个主题材料,FCL定义多少个System.Threading.SynchronizationContext(线程同步上下文)的基类,其派生对象承当将一个应用程序模型连接到它的线程管理模型。

GUI线程都有贰个和它涉及的SynchronizationContext派生对象,使用其静态Current属性获取:SynchronizationContext sc = SynchronizationContext.Current; 将此目标传给其余线程,当二个线程池线程须求让GUI线程更新UI时,调用该指标的sc.Post方法,向Post传递贰个相配SendOrPostCallback委托签字的回调方法(日常是更新UI的操作方法,由GUI线程去奉行),以致三个要传给回调方法的实参。

SynchronizationContext 的Post方法和Send方法的界别:(分别对应于异步/同步调用)

Post方法将回调方法送人GUI线程的队列,允许程序池线程立即返回,不进行阻塞;Post方法内部调用了BeginInvoke方法;

Send方法也将回调方法送人GUI线程的队列,但随后就会阻塞线程池线程,直到GUI线程完成对回调方法的调用。阻塞线程池线程极有可能造成线程池创建一个新的线程,避免调用该方法;Send方法内部调用了Invoke方法; 

对winform来讲是 System.Windows.Forms.WindowsFormsSynchronizationContext是其子类.

Winform窗口冒出后,UI线程 SynchronizationContext.Current会被绑定赋值,独有UI线程的Current不为null。

Public class SendOrPostUI {
   public static void Go() {
      System.Windows.Forms.Application.Run(new MyWindowsForm());
   }
   private static AsyncCallback SyncContextCallback(AsyncCallback callback) {
      // Capture the calling thread's SynchronizationContext-derived object
      SynchronizationContext sc = SynchronizationContext.Current;
      // If there is no SC, just return what was passed in
      if (sc == null) return callback;
      // Return a delegate that, when invoked, posts to the captured SC a method that 
      // calls the original AsyncCallback passing it the IAsyncResult argument
      return asyncResult => sc.Post(result => callback((IAsyncResult)result), asyncResult);
   }
   private sealed class MyWindowsForm : System.Windows.Forms.Form {
      public MyWindowsForm() {
         Text = "Click in the window to start a Web request";
         Width = 400; Height = 100;
      }
      protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) {
         // The GUI thread initiates the asynchronous Web request 
         Text = "Web request initiated";
         var webRequest = WebRequest.Create("http://Wintellect.com/");
         webRequest.BeginGetResponse(SyncContextCallback(ProcessWebResponse), webRequest);
         base.OnMouseClick(e);
      }
      private void ProcessWebResponse(IAsyncResult result) {
         // If we get here, this must be the GUI thread, it's OK to update the UI
         var webRequest = (WebRequest)result.AsyncState;
         using (var webResponse = webRequest.EndGetResponse(result)) {
            Text = "Content length: " + webResponse.ContentLength;
         }
      }
   }
}

正如二种方法其实差不太多,三个是回调内重新卷入,三个是包裹原本的回调。然则SynchronizationContext业务层与UI抽离来说的话是相比较好;

  • 运用task构造函数
  • task工厂类静态方法
  • 使用.NET4.5新引进的Task.run()。

EAP

EAP是为了更便于处理UI的更新推出的模式,主要优点:它同Visual Studio UI设计器进行了很好的集成,可将大多数实现了EAP的类拖放到设计平面(design surface)上,双击控件对应的XXXCompleted事件名,会自动生成事件的回调方法,并将方法同事件自身联系起来。EAP保证事件在应用程序的GUI线程上引发,允许事件回调方法中的代码更新UI控件;

EAP另一重要功能:支持EAP的类自动将应用程序模型映射到它的线程处理模型;EAP类在内部使用SynchronizationContext类。有的EAP类提供了取消、进度报告功能。

   FCL中独有十四个门类达成了EAP形式,常常有二个XXXAsync方法和贰个应和的XXXCompleted事件,甚至这几个情势的共同版本:

*       System.Object的派生类型:*

*                  System.Activies.WorkflowInvoke  *

*                  System.Deployment.Application.ApplicationDeployment*

*                  System.Deployment.Application.InPlaceHosingManager*

*                  System.Net.Mail.SmtpClient*

*                  System.Net.PeerToPeer.PeerNameResolver*

*                  System.Net.PeerToPeer.Collaboration.ContactManager*

*                  System.Net.PeerToPeer.Collaboration.Peer*

*                  System.Net.PeerToPeer.Collaboration.PeerContact*

*                  System.Net.PeerToPeer.Collaboration.PeerNearMe*

*                  System.ServiceModel.Activities.WorkflowControlClient*

*                  System.ServiceModel.Discovery.AnnoucementClient*

*                  System.ServiceModel.Discovery.DiscoveryClient*

*      System.ComponentModel.Component的派生类型:*

                  System.ComponentModel.BackgroundWorker

                  System.Media.SoundPlay

                  System.Net.WebClient

                  System.Net.NetworkInformation.Ping

                  System.Windows.Forms.PictureBox(承接于Control类,Control类派生于Component类)

private sealed class MyForm : System.Windows.Forms.Form {
    protected override void OnClick(EventArgs e) {
      // The System.Net.WebClient class supports the Event-based Asynchronous Pattern
      WebClient wc = new WebClient();
      // When a string completes downloading, the WebClient object raises the 
      // DownloadStringCompleted event which will invoke our ProcessString method         
      wc.DownloadStringCompleted += ProcessString;
      // Start the asynchronous operation (this is like calling a BeginXxx method)
      wc.DownloadStringAsync(new Uri("http://Wintellect.com"));
      base.OnClick(e);
    }
    // This method is guaranteed to be called via the GUI thread
    private void ProcessString(Object sender, DownloadStringCompletedEventArgs e) {
      // If an error occurred, display it; else display the downloaded string
      System.Windows.Forms.MessageBox.Show((e.Error != null) ? e.Error.Message : e.Result);
      }
   }

BackgroundWorker:独有该品种用于可用以施行异步的乘除范围的办事;提供多少个事件:

DoWork:向这几个事件登记的章程应该包蕴总结范围的代码。那个事件由一个线程池线程调用RunWorkerAsync(多个重载方法,带参的不二等秘书诀是向DoWork登记的不二等秘书诀的DoWorkEventArgs参数对象的Argument属性传值,只好在注册的方法中(如e.Argument)获取,Result属性必得设置成计算范围的操作希望回到的值)时引发;

ProgressChanged:向这些事件登记的措施应该满含使用进程音讯来更新UI的代码。这几个事件三回九转在GUI线程上迷惑。DoWork登记的方式必得准期调用BackgroundWorker的ReportProgress方法来诱惑ProgressChanged事件;

RunWorkerCompleted:向这几个事件登记的章程应该蕴含使用总结范围操作的结果对UI进行立异的代码。这么些事件三番一次在GUI线程上吸引。Result获取表示异步操作的结果;

公共属性:CancellationPending(标记是不是已号令撤消后台操作)、IsBusy(标识是或不是正在运营异步操作)、WorkReportsProgress(获取/设置是不是报告进程更新)、WorkerSupportsCancellation(获取/设置是或不是协理异步撤除)

国有措施:CancelAsync(央浼撤废挂起的后台操作)、ReportProgress、RunWorkerAsync

异常

可怜不会抛出。在XXXCompleted事件管理方法中,必须询问AsyncCompleted伊夫ntArgs的Exception属性,看它是否null。若是否null,就务须选用if语句判定Exception派生对象的等级次序,实际不是采取catch块。

我们创设二个出口300万个叁10位字符的GUID职务分别采用二种分歧方式得以完成。代码如下 constint RepeatCount = 1000000; //重复次数

TAP

.NET4.0 中引进了新的异步编制程序模型“基于任务的异步编制程序模型(TAP)”,並且推荐大家在开辟新的七十十六线程应用程序中首荐TAP,在.NET4.5中更为对TPL库实行了多量的优化与修改(async和await)。那未来本人先介绍下TAP具备哪些优势:

  1. 义务调整器(TaskScheduler)信赖于底层的线程池引擎,可自定义一个TaskScheduler修正调解算法,同期不改良代码或编制程序模型。通过有个别队列的职分内联化(task inlining)和做事盗取(work-stealing)机制而发起了汪洋职分,Task可感觉大家进步程序质量。
  2. 能够接受PreferFairness标记,获取与ThreadPool.QueueUserWorkItem只怕多少个寄托的BeginInvoke相近的线程池行为。

        3.  轻易完成任务等待、任务废除、三番陆遍职责、非常管理(System.AggregateException)、GUI线程操作。

       4.  在职务运营后,能够任何时候以职分接二连三的款式登记回调。

       5.  充裕利用现存的线程,防止创造不供给的额外线程。

       6.  结合C#5.0引进async和await关键字轻巧达成“异步方法”。

APM转换为TAP:

应用TaskFactory的FromAsync方法,传递多少个实参:BeginXxx方法、EndXxx方法、Object状态、可选的TaskCreationOptions值,再次回到对一个Task对象的援用;

private static void ConvertingApmToTask() {
      // Instead of this:
      WebRequest webRequest = WebRequest.Create("http://Wintellect.com/");
      webRequest.BeginGetResponse(result => {
         WebResponse webResponse = null;
         try {
            webResponse = webRequest.EndGetResponse(result);
            Console.WriteLine("Content length: " + webResponse.ContentLength);
         }
         catch (WebException we) {
            Console.WriteLine("Failed: " + we.GetBaseException().Message);
         }
         finally {
            if (webResponse != null) webResponse.Close();
         }
      }, null);
      Console.ReadLine();  // for testing purposes
      // Make a Task from an async operation that FromAsync starts
      webRequest = WebRequest.Create("http://Wintellect.com/");
      var t1 = Task.Factory.FromAsync<WebResponse>(webRequest.BeginGetResponse, webRequest.EndGetResponse, null, TaskCreationOptions.None);
      var t2 = t1.ContinueWith(task => {
         WebResponse webResponse = null;
         try {
            webResponse = task.Result;
            Console.WriteLine("Content length: " + webResponse.ContentLength);
         }
         catch (AggregateException ae) {
            if (ae.GetBaseException() is WebException)
               Console.WriteLine("Failed: " + ae.GetBaseException().Message);
            else throw;
         }
         finally { if (webResponse != null) webResponse.Close(); }
      });
      try {t2.Wait();  // for testing purposes only}
      catch (AggregateException) { }
   }

EAP转换成TAP:

动用System.Threading.Tasks.TaskCompletionSource类实行包装;

图片 6

当组织一个TaskCompletionSource对象,也会扭转多个Task,可通过其Task属性获取;当三个异步操作完结时,它应用TaskCompletionSource对象来安装它因为何而成功,撤废,未管理的十三分或者它的结果。调用某些SetXxx方法,能够安装底层Task对象的境况。

private sealed class MyFormTask : System.Windows.Forms.Form {
      protected override void OnClick(EventArgs e) {
         // The System.Net.WebClient class supports the Event-based Asynchronous Pattern
         WebClient wc = new WebClient();
         // Create the TaskCompletionSource and its underlying Task object
         var tcs = new TaskCompletionSource<String>();
         // When a string completes downloading, the WebClient object raises the 
         // DownloadStringCompleted event which will invoke our ProcessString method
         wc.DownloadStringCompleted += (sender, ea) => {
            // This code always executes on the GUI thread; set the Task’s state
            if (ea.Cancelled) tcs.SetCanceled();
            else if (ea.Error != null) tcs.SetException(ea.Error);
            else tcs.SetResult(ea.Result);
         };
         // Have the Task continue with this Task that shows the result in a message box
// NOTE: The TaskContinuationOptions.ExecuteSynchronously flag is required to have this code
         // run on the GUI thread; without the flag, the code runs on a thread pool thread 
         tcs.Task.ContinueWith(t => {
            try { System.Windows.Forms.MessageBox.Show(t.Result);}
            catch (AggregateException ae) {
               System.Windows.Forms.MessageBox.Show(ae.GetBaseException().Message);
            }
         }, TaskContinuationOptions.ExecuteSynchronously);
         // Start the asynchronous operation (this is like calling a BeginXxx method)
         wc.DownloadStringAsync(new Uri("http://Wintellect.com"));
         base.OnClick(e);
      }
   }

实现了TAP的类:存在XxxTaskAsync的方法, 援救异步操作的打消和速度的报告的功能;

撤消:能够经过同盟式裁撤格局,向异步方法传入CancellationToken 参数,通过调用其ThrowIfCancellationRequested方法来定期检查操作是还是不是曾经撤废;

进度报告:能够通过IProgress<T>接口来落实速度报告的作用;

更新GUI: TaskScheduler.FromCurrentSynchronizationContext()获取同步上下文职分调整器,将关系该对象的有所任务都调治给GUI线程,使任务代码能学有所成更新UI;

private sealed class MyForm : System.Windows.Forms.Form {
        public MyForm() {
            Text = "Synchronization Context Task Scheduler Demo";
            Visible = true; Width = 400; Height = 100;
        }
         private static Int32 Sum(CancellationToken ct, Int32 n) {
        Int32 sum = 0;
        for (; n > 0; n--) {
            // The following line throws OperationCanceledException when Cancel 
            // is called on the CancellationTokenSource referred to by the token
            ct.ThrowIfCancellationRequested();
            //Thread.Sleep(0);   // Simulate taking a long time
            checked { sum += n; }
        }
        return sum;
       }
        private readonly TaskScheduler m_syncContextTaskScheduler =
           TaskScheduler.FromCurrentSynchronizationContext();
        private CancellationTokenSource m_cts;
        protected override void OnMouseClick(System.Windows.Forms.MouseEventArgs e) {
            if (m_cts != null) {    // An operation is in flight, cancel it
                m_cts.Cancel();
                m_cts = null;
            } else {                // An operation is not in flight, start it
                Text = "Operation running";
                m_cts = new CancellationTokenSource();
           // This task uses the default task scheduler and executes on a thread pool thread
                var t = new Task<Int32>(() => Sum(m_cts.Token, 20000), m_cts.Token);
                t.Start();
 // These tasks use the synchronization context task scheduler and execute on the GUI thread
                t.ContinueWith(task => Text = "Result: " + task.Result,
                   CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion,
                   m_syncContextTaskScheduler);
                t.ContinueWith(task => Text = "Operation canceled",
                   CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled,
                   m_syncContextTaskScheduler);
                t.ContinueWith(task => Text = "Operation faulted",
                   CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted,
                   m_syncContextTaskScheduler);
            }
            base.OnMouseClick(e);
        }
}

特别管理

在任务抛出的未管理极度都封装在System.AggregateException对象中。这一个指标会积攒在艺术重返的Task或Task<TResult>对象中,要求经过拜望Wait()、Result、Exception成员技艺观测到不行。(所以,在会见Result在此以前,应先观望IsCanceled和IsFaulted属性)

意气风发经平素不访谈Task的Wait()、Result、Exception成员,那么您将长久注意不到这个特别的发生。为了扶助您检测到那个未管理的这几个,能够向TaskScheduler对象的UnobservedTaskException事件注册回调函数。每当二个Task被垃圾回笼时,假诺存在三个从未有过专心到的可怜,CL宝马X3的扫尾器线程会引发这一个事件。

可在事变回调函数中调用UnobservedTaskExceptionEventArgs对象的SetObserved() 方法来提出已经管理好了十三分,进而阻碍CLXC60终止线程。然则并不推荐这么做,宁愿终止进度也绝不带着曾经毁损的动静继续运营。

            var listGuid = new BlockingCollection<string>();

            //Action无返回值 
            Action dowork = () =>
           {
               for (var count = 0; count < RepeatCount; count++)
               {
                   listGuid.Add(Guid.NewGuid().ToString("N"));
               }
           };
            Task task1 = new Task(dowork);  //1)使用构造函数
            task1.Start();
            Task task2 = Task.Factory.StartNew(dowork); //2)Task工厂方法,直接运行,不需要在调用start()
            Task task3 = Task.Run(dowork); //3)4.5 Task.Run 是Task.Factory.StartNew简化方式;直接运行,不需要在调用start()

            Task.WaitAll(task1, task2, task3); //等待所有任务完成,相当于 thread.join()
            Console.Write($"生成数量:{listGuid.Count / 10000}万");

Async /Await

在.NET Framework 4.0中增多.NET Framework 4.5中新的异步操作库(async/await),该包由四个库组成:Microsoft.Bcl、Microsoft.Bcl.Async和Microsoft.Bcl.Build。

Install-Package Microsoft.Bcl.Async

注:asp.net 框架一定要晋级.net framework框架才干接受 async/await

比如那个音讯是“Message : Could not load file or assembly 'System.Core, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, Retargetable=Yes' or one of its dependencies. The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047)”,

那供给您去微软官方网址下载.net4.0的KB2468871补丁来安装。

C# 5引入了异步函数(asynchrnous function)的定义。日常是指用async修饰符证明的,可

满含await表明式的主意或无名函数;

async关键字创立了叁个状态机,相似于yield return语句;await关键字只可以用于有用async修饰符注明的法子。async修饰符只可以用来再次回到Task/Task<TResult>或void的点子。await只能用来调用再次来到Task/Task<TResult>的主意;await会祛除线程的堵塞,完毕调用的任务;等待职勒令功后,获取结果,然后施行await关键字背后的代码;编写翻译器会把await的表达式后的代码应用 Task.ContinueWith 包装了四起,回调时私下认可使用当前线程的风度翩翩道上下文任务调解器;如若不应用相仿的一路上下文,必得调用Task实例的ConfigureAwait(false)方法;

await msg.Content.ReadAsStringAsync().ConfigureAwait(false);

异步方法的宣示语法与其余艺术完全等同,只是要饱含async上下文关键字。async能够出

现行归来类型从前的其余岗位。async修饰符在改造的代码中尚无效应,也可省略不写,它分明发表了你的预想,告诉编写翻译器能够主动搜寻await表达式,也足以搜寻应该调换到异步调用和await表达式的块调用。

调用者和异步方法之间是透过再次来到值来通讯的。异步函数的回到类型只好为:

Void 、Task、Task<TResult>;Task和Task<TResult>类型都代表二个或者还未遂的操作。 Task<TResult>承袭自Task。二者的区分是,Task<TResult>表示一个再次回到值为T类型的操作,而Task则不须求发出重回值。在某种意义上,你能够以为Task就是Task<void>类型;

因此将异步方法设计为能够回到void,是为着和事件管理程序包容。

异步方法签字的束缚:全体参数都不能够接受out或ref修饰符。

图片 7

 

输出图片 8

上述实例成立三个并未再次来到值的天职,当然也足以透过Task<TResult> 来创造重返值的异步操作。

一而再义务

率先个任务生成叁十三位字符的Guid义务,利用重临的结果再转造成对应的ASCII码,最后ASCII码十进制的值相加。代码如下 

 //Func 
            Func<string> doWork = () =>
            {
                return Guid.NewGuid().ToString("N");
            };
            //延续任务
            var task = Task.Run(doWork).ContinueWith(async strGuid =>
            {
                var resut = await strGuid;
                var array = Encoding.ASCII.GetBytes(resut);

                int mLenght = array.Length;
                int sumResult = 0;
                for (int m = 0; m < mLenght; m++)
                {
                    sumResult += array[m];
                }
                Console.WriteLine($"Guid对应10进制相加结果:{sumResult}");
            });

输出图片 9 

管理义务特别

一同代码要想捕获格外,只需在代码块上增多Try ...Catch就可以。不过异步调用不能够那样做。因为调整会登时从调用重返,然后调节会离开Try块,而那时候间隔工小编线程发生万分也许还应该有漫长呢。

为了管理失误的天职,三个技巧是显式创立一而再一而再职务作为那七个职责的“错误管理程序”。检查评定到先驱职务引发未管理的丰硕,职务调解器会自动调解一连职分。可是,若无这种管理程序,同不经常间在一差二错的任务上实行wait()(或其余试图拿走result的动作),就能够引发三个AggregateException,示例代码如下。

  Task task = Task.Run(() =>
            {
                throw new InvalidOperationException();
            });

            try
            {
                task.Wait();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"常规erro:{ex.Message};type:{ex.GetType()}");
                AggregateException excetion = (AggregateException)ex;
                excetion.Handle(eachException =>
                {
                    Console.WriteLine($"erro:{eachException.Message}");
                    return true;
                });
            }

输出图片 10

虽说工笔者线程寒食发的未管理分外是InvalidOperationException类型,但主线程捕捉的仍然为二个AggregateException。由于编写翻译时不知晓工小编职责将要引发贰个照旧多个拾壹分,所以未管理的失误任务一而再吸引一个AggregateException。

  还可查阅职务的Exception属性来询问出错职分的图景,那样不会产生在脚下线程上再也掀起这三个。代码如下

  bool paraentTaskFaulted = false;
            Task task = new Task(() =>
            {
                throw new InvalidOperationException();
            });

            Task continuationTask = task.ContinueWith(t =>
            {

                paraentTaskFaulted = t.IsFaulted;
            }, TaskContinuationOptions.OnlyOnFaulted);

            task.Start();
            Console.Write(continuationTask.Status);
            continuationTask.Wait();
            //如果断言失败 则显示一个消息框,其中显示调用堆栈。
            Trace.Assert(paraentTaskFaulted);
            if (!task.IsFaulted)
            {
                task.Wait();
            }
            else
            {
                task.Exception.Handle(eachException =>
                {
                    Console.WriteLine($"erro:{eachException.Message}");
                    return true;
                });
            }

 

注意,为了获取原始义务上的未管理极度,大家使用Exception属性。结果和地点示例输出相符。

废除职务

 职分帮忙撤销,比方常用在指依时期内的天职依旧依附有些条件手动的吊销,扶持撤消的职务要监听一个CancellationToken对象。职分轮询它,检查是还是不是出发了撤回伏乞。如下代码体现了收回乞求和对恳求的响应。

 /// <summary>
        /// 取消任务
        /// </summary>
        public void TaskTopic5()
        {
            string stars = "*".PadRight(Console.LargestWindowWidth-1,'*');
            Console.WriteLine("push enter to exit.");
            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); //向应该被取消的 System.Threading.CancellationToken 发送信号
            Task task = Task.Run(
                ()=>
                Count(cancellationTokenSource.Token,100),
                cancellationTokenSource.Token);

            Console.Read();
            cancellationTokenSource.Cancel();//按下enter键, 传达取消请求

            Console.WriteLine(stars);
            Console.WriteLine(task.IsCanceled);
            task.Wait();
            Console.WriteLine();
        }
        /// <summary>
        /// 数数
        /// </summary>
        /// <param name="token"></param>
        /// <param name="countTo"></param>
        private void Count(CancellationToken token,int countTo)
        {
            for (int count = 1; count < countTo; count++)
            {
                //监控是否取消
                if (token.IsCancellationRequested)
                {
                    Console.WriteLine("数数喊停了");
                    break;
                }

                Console.Write(count+"=》");
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
            Console.WriteLine("数数结束");
        }

 

输出图片 11

  调用Cancel()实际会在从cancellationTokenSource.Token复制的兼具撤除标识上设置IsCancellationRequested属性。

 到此职责的一些大旨的操作已经到位了,下风流浪漫节关切下C#5.0的async/await上下文关键字。

本文由澳门至尊网站发布于免费资源,转载请注明出处:异步编制程序

关键词: