zoukankan      html  css  js  c++  java
  • TaskCompletionSource使用场景

    TaskCompletionSource生成Task的另一种方法.使用TaskCompletionSource很简单,只需要实例化它即可。TaskCompletionSource有一个Task属性,你可以对该属性暴露的task做操作,比如让它wait或者ContinueWith等操作。当然,这个task由TaskCompletionSource完全控制。

    使用模拟一个Task.Run()

    public static Task<TResult> Run<TResult>(Func<TResult> func)
            {
                TaskCompletionSource<TResult> tcs = new TaskCompletionSource<TResult>();
                var t = new Thread(() => {
                    try
                    {
                        tcs.SetResult( func());
                    }
                    catch (Exception ex)
                    {
                        tcs.SetException(ex);
                    }
                });
                t.IsBackground = true;
                t.Start();
                return tcs.Task;
            }
    

    封装回调方式的异步处理

        class Program
        {
            static void Main(string[] args)
            {
                var t = EventWrap();
                Console.WriteLine(t.Result);
                Console.ReadKey();
            }
    
            static Task<string> EventWrap()
            {
                var tcs = new TaskCompletionSource<string>();
                var eventClass = new EventClass();
                eventClass.Done += (args) => { 
                    tcs.SetResult(args); };
                return tcs.Task;
            }
        }
    
        public class EventClass
        {
            public EventClass()
            {
                Task.Delay(2000).ContinueWith(t =>this.Do());
            }
            public Action<string> Done = (args) => { };
            public void Do()
            {
                Done("Done");
            }
        }
    

    可指定处理线程数的异步任务队列:

    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication6
    {
        public class PCQueue : IDisposable
        {
            class WorkItem
            {
                public readonly TaskCompletionSource<object> TaskSource;
                public readonly Action Action;
                public readonly CancellationToken? CancelToken;
    
                public WorkItem(
                  TaskCompletionSource<object> taskSource,
                  Action action,
                  CancellationToken? cancelToken)
                {
                    
                    TaskSource = taskSource;
                    Action = action;
                    CancelToken = cancelToken;
                }
            }
    
            BlockingCollection<WorkItem> _taskQ = new BlockingCollection<WorkItem>();
    
            /// <summary>
            /// 为每个消费者创建并启动单独的任务: 这里我启动了2个任务,用于打印easy和easy2这两个的顺序不一定
            /// </summary>
            /// <param name="workerCount"></param>
            public PCQueue(int workerCount)
            {
                // 为每个消费者创建并启动单独的任务:
                for (int i = 0; i < workerCount; i++)
                    Task.Factory.StartNew(Consume);
            }
    
            public void Dispose() { _taskQ.CompleteAdding(); }
    
            /// <summary>
            /// 默认任务取消标识为null的任务进队方法
            /// </summary>
            /// <param name="action"></param>
            /// <returns></returns>
            public Task EnqueueTask(Action action)
            {
                return EnqueueTask(action, null);
            }
            /// <summary>
            /// 任务进队方法含标识
            /// </summary>
            /// <param name="action"></param>
            /// <param name="cancelToken"></param>
            /// <returns></returns>
            public Task EnqueueTask(Action action, CancellationToken? cancelToken)
            {
                var tcs = new TaskCompletionSource<object>();
                _taskQ.Add(new WorkItem(tcs, action, cancelToken));
                //通过TaskCompletionSource返回任务本身,可查看任务的响应信息如result,exception,status等等
                return tcs.Task;
            }
    
            void Consume()
            {
                foreach (WorkItem workItem in _taskQ.GetConsumingEnumerable())
                    if (workItem.CancelToken.HasValue &&
                        workItem.CancelToken.Value.IsCancellationRequested)
                    {
                        workItem.TaskSource.SetCanceled();
                    }
                    else
                        try
                        {
                            workItem.Action();
                            workItem.TaskSource.SetResult(1234);   // 表示完成
                        }
                        catch (OperationCanceledException ex)
                        {
                            if (ex.CancellationToken == workItem.CancelToken)
                                workItem.TaskSource.SetCanceled();
                            else
                                workItem.TaskSource.SetException(ex);
                        }
                        catch (Exception ex)
                        {
                            workItem.TaskSource.SetException(ex);
                        }
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                CancellationToken token1 = new CancellationToken(true);
                //
                var pcQ = new PCQueue(2);
                Task task = pcQ.EnqueueTask(() => Console.WriteLine("Easy!"),token1);//输出easy的任务不会执行
                task = pcQ.EnqueueTask(() => Console.WriteLine("Easy2!"));//会执行
             
                // ...
                Console.Read();
            }
        }
    }
    

    案例

                var waitForStop = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
                CancellationTokenSource source = new CancellationTokenSource();
                Console.WriteLine("3秒后取消");
                Task.Delay(3000).ContinueWith(t => source.Cancel());
                source.Token.Register(state =>
                {
                    var tcs = (TaskCompletionSource<object>)state;
                    tcs.TrySetResult(null);
                }, waitForStop);
                Console.WriteLine("正在执行");
                await waitForStop.Task;
                Console.WriteLine("执行完成");
    
  • 相关阅读:
    【ARM】2440裸机系列-RTC数字时钟
    【ARM】2440裸机系列-图片显示
    【Acm】算法之美—Anagrams by Stack
    【C/C++】程序如何来,编译全过程
    【Cmd】批处理
    【Cmd】那些年,我们迷恋的cmd命令(二)
    【Cmd】那些年,我们迷恋的cmd命令(一)
    【web技术】html特效代码(二)
    【web技术】html特效代码(一)
    【安全】加密解密整理
  • 原文地址:https://www.cnblogs.com/fanfan-90/p/13585619.html
Copyright © 2011-2022 走看看