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");
}
}
}