c# TaskCompletionSource

对TaskCompletionSource完全不清楚,msdn上有介绍:https://technet.microsoft.com/zh-cn/library/dd449174(v=vs.110).aspx,

https://www.cnblogs.com/farb/p/4870421.html,

https://msdn.microsoft.com/zh-cn/library/dd997423(v=vs.100).aspx,

https://msdn.microsoft.com/zh-cn/library/dd537609(v=vs.100).aspx,

https://msdn.microsoft.com/zh-cn/library/dd997423(v=vs.100).aspx中有一句:TaskCompletionSource<TResult> 创建的任何任务将由 TaskCompletionSource 启动,因此,用户代码不应在该任务上调用 Start 方法。

还有一篇TaskCompletionSource相关的异步编程好帖子 全面解析C#中的异步编程 https://www.cnblogs.com/xiaoyaojian/p/4603238.html 其中有一段代码做实验应该会有收获:

static async void ReadAssignedFile()
        {
            byte[] buffer;
            try
            {
                double length = await ReadFileAsync("SomeFileDoNotExisted.txt", out buffer);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        static Task<double> ReadFileAsync(string filePath,out byte[] buffer) 
        {
            Stream stream = File.Open(filePath, FileMode.Open);
            buffer = new byte[stream.Length];
            var tcs = new TaskCompletionSource<double>();
            stream.BeginRead(buffer, 0, buffer.Length, arr =>
            {
                try
                {
                    var length = stream.EndRead(arr);
                    tcs.SetResult(stream.Length);
                }
                catch (IOException ex)
                {
                    tcs.SetException(ex);
                }
            }, null);
            return tcs.Task;
        }

https://msdn.microsoft.com/zh-cn/magazine/ff959203.aspx

https://msdn.microsoft.com/zh-cn/library/ee622454(v=vs.100).aspx 也有介绍,现在开始做实验:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TaskCompletionSourceDemo
{
    class WebDataDownloader
    {
        static void Main()
        {
            WebDataDownloader downloader = new WebDataDownloader();
            string[] addresses = { "http://www.baidu.com", "http://www.yahoo.com",
                                 "http://www.sina.com", "http://www.qq.com" };
            CancellationTokenSource cts = new CancellationTokenSource();

            // Create a UI thread from which to cancel the entire operation
            Task.Factory.StartNew(() =>
            {
                Console.WriteLine("Press c to cancel");
                if (Console.ReadKey().KeyChar == 'c')
                    cts.Cancel();
            });

            // Using a neutral search term that is sure to get some hits.
            Task<string[]> webTask = downloader.GetWordCounts(addresses, "the", cts.Token);

            // Do some other work here unless the method has already completed.
            if (!webTask.IsCompleted)
            {
                // Simulate some work.
                Thread.SpinWait(5000000);
            }

            string[] results = null;
            try
            {
                results = webTask.Result;
            }
            catch (AggregateException e)
            {
                foreach (var ex in e.InnerExceptions)
                {
                    OperationCanceledException oce = ex as OperationCanceledException;
                    if (oce != null)
                    {
                        if (oce.CancellationToken == cts.Token)
                        {
                            Console.WriteLine("Operation canceled by user.");
                        }
                    }
                    else
                        Console.WriteLine(ex.Message);
                }
            }

            if (results != null)
            {
                foreach (var item in results)
                    Console.WriteLine(item);
            }
            Console.ReadKey();
        }

        Task<string[]> GetWordCounts(string[] urls, string name, CancellationToken token)
        {
            TaskCompletionSource<string[]> tcs = new TaskCompletionSource<string[]>();
            WebClient[] webClients = new WebClient[urls.Length];

            // If the user cancels the CancellationToken, then we can use the
            // WebClient's ability to cancel its own async operations.
            token.Register(() =>
            {
                foreach (var wc in webClients)
                {
                    if (wc != null)
                        wc.CancelAsync();
                }
            });

            object m_lock = new object();
            int count = 0;
            List<string> results = new List<string>();
            for (int i = 0; i < urls.Length; i++)
            {
                webClients[i] = new WebClient();

                #region callback
                // Specify the callback for the DownloadStringCompleted
                // event that will be raised by this WebClient instance.
                webClients[i].DownloadStringCompleted += (obj, args) =>
                {
                    if (args.Cancelled == true)
                    {
                        tcs.TrySetCanceled();
                        return;
                    }
                    else if (args.Error != null)
                    {
                        // Pass through to the underlying Task
                        // any exceptions thrown by the WebClient
                        // during the asynchronous operation.
                        tcs.TrySetException(args.Error);
                        return;
                    }
                    else
                    {
                        // Split the string into an array of words,
                        // then count the number of elements that match
                        // the search term.
                        string[] words = null;
                        words = args.Result.Split(' ');
                        string NAME = name.ToUpper();
                        int nameCount = (from word in words.AsParallel()
                                         where word.ToUpper().Contains(NAME)
                                         select word)
                                        .Count();

                        // Associate the results with the url, and add new string to the array that 
                        // the underlying Task object will return in its Result property.
                        results.Add(String.Format("{0} has {1} instances of {2}", args.UserState, nameCount, name));
                    }

                    // If this is the last async operation to complete,
                    // then set the Result property on the underlying Task.
                    lock (m_lock)
                    {
                        count++;
                        if (count == urls.Length)
                        {
                            tcs.TrySetResult(results.ToArray());
                        }
                    }
                };
                #endregion

                // Call DownloadStringAsync for each URL.
                Uri address = null;
                try
                {
                    address = new Uri(urls[i]);
                    // Pass the address, and also use it for the userToken 
                    // to identify the page when the delegate is invoked.
                    webClients[i].DownloadStringAsync(address, address);
                }

                catch (UriFormatException ex)
                {
                    // Abandon the entire operation if one url is malformed.
                    // Other actions are possible here.
                    tcs.TrySetException(ex);
                    return tcs.Task;
                }
            }

            // Return the underlying Task. The client code
            // waits on the Result property, and handles exceptions
            // in the try-catch block there.
            return tcs.Task;
        }
    }
}

程序执行的结果如下:

Press c to cancel
http://www.baidu.com/ has 1 instances of the
http://www.qq.com/ has 72 instances of the
http://www.sina.com/ has 2 instances of the
http://www.yahoo.com/ has 0 instances of the

猜你喜欢

转载自my.oschina.net/u/2963604/blog/1818669
C#
今日推荐