Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asynchronous 如何使用TaskCompletionSource_Asynchronous_.net Core_Task Parallel Library_Taskcompletionsource - Fatal编程技术网

Asynchronous 如何使用TaskCompletionSource

Asynchronous 如何使用TaskCompletionSource,asynchronous,.net-core,task-parallel-library,taskcompletionsource,Asynchronous,.net Core,Task Parallel Library,Taskcompletionsource,我的情况是多生产商和单一消费者。我选择了一个通用的线程安全的资源,所有生产商将项目排队。 但是,我不知道如何有效地让制作人在从该资源出列时等待新项目 POCO struct Sample { public int Id { get; set; } public double Value { get; set; } } 制作人 class ProducerGroup { StorageQueue sink;

我的情况是多生产商和单一消费者。我选择了一个通用的
线程安全的
资源,所有生产商
项目排队。 但是,我不知道如何有效地让制作人在
从该资源出列时等待新项目

POCO

struct Sample
    {
        public int Id { get; set; }
        public  double Value { get; set; }
    }
制作人

class ProducerGroup
    {
        StorageQueue sink;
        int producerGroupSize;

        public ProducerGroup(StorageQueue _sink,int producers)
        {
            this.sink = _sink;
            this.producerGroupSize = producers;
        }
        public void StartProducers()
        {
            Task[] producers = new Task[producerGroupSize];
            int currentProducer;
            for (int i = 0; i < producerGroupSize; i++)
            {
                currentProducer = i;
                producers[i] = Task.Run(async () =>
                  {
                      int cycle = 0;
                      while (true)
                      {
                          if (cycle > 5)
                          {
                              cycle = 0;
                          }
                          Sample localSample = new Sample { Id = currentProducer, Value = cycle++ };
                          await Task.Delay(1000);
                          this.sink.Enqueue(localSample);
                      }
                  });
            }

        }
    }
正如您在
消费者
类中所看到的,我想将
存储的方法
打包到
任务
中,这样我就可以在
消费者
中等待
了。
我使用
TaskCompletionSource
的唯一原因是能够在
Storage`中的
Dequeue
Enqueue
方法之间进行通信

我不知道是否需要重新初始化
tcs
,但我想我需要这样做,因为我希望在每次
排队
操作后都有一个新的
任务

我还重新初始化了
锁中的
tcs
,因为我希望特定实例设置结果


我应该如何进行这项工作?实现是否正常?
System.Reactive
会提供更好的选择吗?

我认为您的实现中存在几个问题:

  • 如果多次调用
    Enqueue()
    而未调用
    DequeueAsync()
    ,则会丢失
    TaskCompletionSource
    ,而只有最后一个。然后,在第一次调用后,调用
    DequeueAsync()
    将不会产生正确的结果 要解决此问题,您需要为此设置一个
    TaskCompletionSource
    队列。看一看,再进一步

    如果队列为空,最好在
    DequeueAsync
    中使用以正确等待

  • DequeueAsync()
    中也不保护队列

  • 生产者/消费者模式有很多选择,可以尝试,也可以选择
    class StorageQueue
        {
            private TaskCompletionSource<Sample> tcs;
            private object @lock = new object();
    
            private Queue<Sample> queue;
    
            public static StorageQueue CreateQueue(int?size=null)
            {
                return new StorageQueue(size);
            }
    
            public StorageQueue(int ?size)
            {
                if (size.HasValue)
                {
                    this.queue = new Queue<Sample>(size.Value);
                }
                else
                    this.queue = new Queue<Sample>();
            }
    
            public void Enqueue(Sample value)
            {
                lock (this.@lock)
                {
                    this.queue.Enqueue(value);
                    tcs = new TaskCompletionSource<Sample>();
                    tcs.SetResult(this.queue.Peek());
                }
            }
            public async Task<Sample> DequeueAsync()
            {
                var result=await this.tcs.Task;
                this.queue.Dequeue();
                return result;
            }
        }
    
    class Consumer
        {
            private StorageQueue source;
            public Consumer(StorageQueue _source)
            {
                this.source = _source;
            }
            public async Task ConsumeAsync()
            {
                while (true)
                {
                    Sample arrivedSample = await this.source.DequeueAsync();  //how should i implement this ?
                    Console.WriteLine("Just Arrived");
                }
            }
        }