• 生产消费者队列(TaskCompletionSource)的应用


    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();
            }
        }
    }
  • 相关阅读:
    c# 测试篇之Linq性能测试
    F# 笔记
    c# DataSource和BindingSource
    .net中配置的保存格式笔记
    泛型约束(转)
    c# 调用showDialog后需要Dispose
    c# 实现ComboBox自动模糊匹配
    c# 二进制或算法实现枚举的HasFlag函数
    C# WinForm自定义控件整理
    微软中文MSDN上的一些文章链接
  • 原文地址:https://www.cnblogs.com/kexb/p/6793154.html
Copyright © 2020-2023  润新知