Article From:https://www.cnblogs.com/zhlziliaoku/p/9217306.html

First, introduction

  In the last two topics, I introduce the EAP in APM and.NET 2 in.NET 1. When you use the previous two patterns for asynchronous programming, you will feel more or less difficult to realize. First of all, I personally feel that when APM is used,First we have to define the delegate to wrap the callback method, which is a bit cumbersome. However, when using EAP, we need to implement Completed events and Progress events. The two implementations of the above feel a little tedious, and Microsoft also means this.A new asynchronous mode, task based asynchronous mode, is proposed in.NET 4, which mainly uses System.Threading.Tasks.Task and Task< T> classes complete asynchronous programming with respect to the previous two types of asynchronismIn model, TAP makes the asynchronous programming model more simple (because we only need to pay attention to the use of the Task), and TAP is also the asynchronous programming model recommended by Microsoft, and the following will be specific for you to share the subject.

Two. What is TAP? Introduction to task based asynchronous mode

Task-based Asynchronous Pattern (TAP), which is recommended by Microsoft, mainly uses a simple, task based asynchronous mode to represent the start and completion of asynchronous operations, but asynchronous programmingThe model (APM) requires two methods of BeginXxx and EndXxx to represent the start and completion of asynchronous operations (which is complex to use), however, the event based asynchronous mode (EAP) requires a method with a Async suffix and one or more events, events, and eventsProcess and event parameters. See here, whether we all have such a question – how do we distinguish the task based asynchronous mode from the class in the.NET class library, which is simple to represent the class implementation when the TaskAsync is seen in the class as a suffix.TAP, and the task based asynchronous mode also supports the function of the cancellation and progress reporting of asynchronous operations, but these two implementations are not as complex as the implementation in EAP, because if we are to implement the class of EAP by ourselves, we need to define the delegate type of multiple events and event handlers.And the parameters of the event (which can be seen in the BackgroundWorker parsing section of the previous topic), but in the TAP implementation, we only need to pass the CancellationToken parameter to the asynchronous method, because the parameter is within the asynchronous method.The IsCancellationRequested property of the number is monitored, and when an asynchronous method receives a cancellation request, the asynchronous method will exit the execution (specifically this can use a reflection tool to view the DownloadDataTaskAs of the WebClient.The YNC method can also refer to the asynchronous method based on task asynchronous mode implemented by the latter part of my own. In TAP, we can realize the function of the progress report through IProgress&lt, T&gt, interface, and can refer to the procedure part of my application later.

I have not yet found the function of the class that provides progress reports in the.NET class library. The following will demonstrate this implementation, and are the highlights of the program, and further understand the asynchronous mode based on the task by implementing the asynchronous method of the TAP..

Three, how to use TAP — asynchronous programming using task based asynchronous mode.

 After looking at the above introduction, we can’t wait to know how to implement an asynchronous approach to a task based asynchronous mode, and hope that this method can complete the function of the cancellation and progress report of the asynchronous operation (because the other events and the definition of event parameters need to be realized in EAP.Type, such an implementation is rather complicated. The following is based on task based asynchronous mode, which is implemented on the topic. Now let’s implement our asynchronous method.

        //  Download File
        // CancellationToken Parameter assignment to get a cancellation request// progressParameter in charge of progress report
        private void DownLoadFile(string url, CancellationToken ct, IProgress<int> progress)
        {
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            Stream responseStream = null;
            int bufferSize = 2048;
            byte[] bufferBytes = new byte[bufferSize];
            try
            {
                request = (HttpWebRequest)WebRequest.Create(url);
                if (DownloadSize != 0)
                {
                    request.AddRange(DownloadSize);
                }
                response = (HttpWebResponse)request.GetResponse();
                responseStream = response.GetResponseStream();
                int readSize = 0;
                while (true)
                {
                    // The cancellation request is sent out of the asynchronous operation
                    if (ct.IsCancellationRequested == true)
                    {
                        MessageBox.Show(String.Format("Download the pause, download the file address: the number of bytes that {0}\n has downloaded is: {1} bytes.", downloadPath, DownloadSize));

                        response.Close();
                        filestream.Close();
                        sc.Post((state) =>
                        {
                            this.btnStart.Enabled = true;
                            this.btnPause.Enabled = false;
                        }, null);
                        // Exit asynchronous operation
                        break;
                    }
                    readSize = responseStream.Read(bufferBytes, 0, bufferBytes.Length);
                    if (readSize > 0)
                    {
                        DownloadSize += readSize;
                        int percentComplete = (int)((float)DownloadSize / (float)totalSize * 100);
                        filestream.Write(bufferBytes, 0, readSize);
                        // Report progress
                        progress.Report(percentComplete);
                    }
                    else
                    {
                        MessageBox.Show(String.Format("Download has been completed, download the file address: {0}, the total number of bytes of the file is {1} bytes.", downloadPath, totalSize));
                        sc.Post((state) =>
                        {
                            this.btnStart.Enabled = false;
                            this.btnPause.Enabled = false;
                        }, null);
                        response.Close();
                        filestream.Close();
                        break;
                    }
                }      
            }
            catch (AggregateException ex)
            {
                // Because calling the Cancel method throws OperationCanceledException exceptions.// Treat any OperationCanceledException object as processing.
                ex.Handle(e => e is OperationCanceledException);
            }
        }
        // Start DownLoad File
        private void btnStart_Click(object sender, EventArgs e)
        {
            filestream = new FileStream(downloadPath, FileMode.OpenOrCreate);
            this.btnStart.Enabled = false;
            this.btnPause.Enabled = true;
            filestream.Seek(DownloadSize, SeekOrigin.Begin);
            // Capture the synchronous context derived object of the calling thread
            sc = SynchronizationContext.Current;
            cts = new CancellationTokenSource();
            // Initialize a new Task with the specified operation.
            task = new Task(() => Actionmethod(cts.Token), cts.Token);
            // Start Task and arrange it to the current TaskScheduler.
            task.Start();
            //await DownLoadFileAsync(txbUrl.Text.Trim(), cts.Token,new Progress<int>(p => progressBar1.Value = p));
        }
        // A method of execution in a task
        private void Actionmethod(CancellationToken ct)
        {
            // Using the synchronous Post method in the text, update the UI method to allow the main thread to execute.
            DownLoadFile(txbUrl.Text.Trim(), ct, new Progress<int>(p => 
                {
                    sc.Post(new SendOrPostCallback((result)=>progressBar1.Value=(int)result),p);
                }));
        }
        // Pause Download
        private void btnPause_Click(object sender, EventArgs e)
        {
            // Send out a cancellation request
            cts.Cancel();
        }

Four, TAP and APM or EAP can be converted? Conversion from other asynchronous modes

From the above code, we can clearly find that the task based asynchronous mode is really easier to use than the previous two asynchronous modes, so from.NET Framework 4, Microsoft recommends TAP for asynchronous programming, which involves the previous use of APMOr how to transfer the programs implemented by EAP to the problems implemented by TAP, and.NET Framwwork also supports the transformation between them.

4.1 Convert APM to TAP

In the System.Threading.Tasks namespace, there is a TaskFactory (task Engineering) class, and we can use the FromAsync method of this class to convert APM to TAP, with task based asynchronous modeAn example of the implementation of the asynchronous programming model.

        // You can compare the two implementations
        #region Using APM to implement asynchronous requestsprivate void APMWay()
        {
            WebRequest webRq = WebRequest.Create("http://msdn.microsoft.com/zh-CN/");
            webRq.BeginGetResponse(result =>
            {
                WebResponse webResponse = null;
                try
                {
                    webResponse = webRq.EndGetResponse(result);
                    Console.WriteLine("The content of the request is as follows:" + webResponse.ContentLength);
                }
                catch (WebException ex)
                {
                    Console.WriteLine("Exceptions occur, and the exception information is:" + ex.GetBaseException().Message);
                }
                finally
                {
                    if (webResponse != null)
                    {
                        webResponse.Close();
                    }
                }
            }, null);
        }
        #endregion
        #region Using the FromAsync method to convert APM to TAPprivate void APMswitchToTAP()
        {
            WebRequest webRq = WebRequest.Create("http://msdn.microsoft.com/zh-CN/");
            Task.Factory.FromAsync<WebResponse>(webRq.BeginGetResponse, webRq.EndGetResponse, null, TaskCreationOptions.None).
                ContinueWith(t =>
                {
                    WebResponse webResponse = null;
                    try
                    {
                        webResponse = t.Result;
                        Console.WriteLine("The content of the request is as follows:" + webResponse.ContentLength);
                    }
                    catch (AggregateException ex)
                    {
                        if (ex.GetBaseException() is WebException)
                        {
                            Console.WriteLine("Exceptions occur, and the exception information is:" + ex.GetBaseException().Message);
                        }
                        else
                        {
                            throw;
                        }
                    }
                    finally
                    {
                        if (webResponse != null)
                        {
                            webResponse.Close();
                        }
                    }
                });
        }
        #endregion

The above code demonstrates the use of the original implementation of APM and how to use the FromAsync method to transform the implementation of APM into TAP, and put these two ways together. One is to help everyone to make a contrast and make it easier to understand the conversion of APM to TAP.Two, we can see the difference between TAP and APM through the above comparison.

4.2 Transform EAP into TAP

Processing APM can be upgraded to be implemented with TAP, and for EAP, we can also convert it to TAP, and the following code demonstrates how to convert EAP to TAP:

#region The implementation of converting EAP to TAP// webClientClass support asynchronous mode based on event - based (EAP)
            WebClient webClient = new WebClient();

            // Create TaskCompletionSource and its underlying Task objects
            TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();

            // After a string is downloaded, the WebClient object should issue the DownloadStringCompleted event.
            webClient.DownloadStringCompleted += (sender, e) =>
            {
                // The following code is executed on the GUI thread// Setting the Task state
                if (e.Error != null)
                {
                    // Attempt to convert basic Tasks.Task< TResult> to Tasks.TaskStatus.Faulted state.
                    tcs.TrySetException(e.Error);
                }
                else if (e.Cancelled)
                {
                    // Attempt to convert basic Tasks.Task< TResult> to Tasks.TaskStatus.Canceled state.
                    tcs.TrySetCanceled();
                }
                else
                {
                    // Try to convert basic Tasks.Task< TResult> to TaskStatus.RanToCompletion state.
                    tcs.TrySetResult(e.Result);
                }
            };

            // When Task completes, continue the following Task to show the state of Task.// In order for the following tasks to be executed on the GUI thread, it must be marked as TaskContinuationOptions.ExecuteSynchronously.// Without this tag, the task code will run on a thread pool thread.
            tcs.Task.ContinueWith(t =>
            {
                if (t.IsCanceled)
                {
                    Console.WriteLine("The operation has been cancelled");
                }
                else if (t.IsFaulted)
                {
                    Console.WriteLine("Exceptions occur, and the exception information is:" + t.Exception.GetBaseException().Message);
                }
                else
                {
                    Console.WriteLine(String.Format("The operation has been completed, and the result is: {0}", t.Result));
                }
            }, TaskContinuationOptions.ExecuteSynchronously);

            // Start asynchronous operation
            webClient.DownloadStringAsync(new Uri("http://msdn.microsoft.com/zh-CN/"));
            #endregion

 

Link of this Article: Task based programming model TAP

Leave a Reply

Your email address will not be published. Required fields are marked *