C# 带队列的异步/同步并发调用

C# 带队列的异步/同步并发调用,c#,concurrency,asynchronous,task,C#,Concurrency,Asynchronous,Task,我有一个场景,我在做一些参与者模型类型的消息查询,我想要一个方法将任务或委托插入队列(可能是新的ConcurrentQueue),等待其他进程处理队列,执行任务,然后返回结果,最好不要锁定。可以同步和异步调用该方法。只能同时运行一个排队操作 我不知道如何以一种有点高绩效的方式完成这项工作,请帮助:) 编辑 这是一个尝试,有人看到这种方法有任何问题吗(排除异常处理)?另外,我可以想象,与简单锁定相比,这会有相当多的开销,与使用异步委托相比,这又是如何呢 public partial class

我有一个场景,我在做一些参与者模型类型的消息查询,我想要一个方法将任务或委托插入队列(可能是新的ConcurrentQueue),等待其他进程处理队列,执行任务,然后返回结果,最好不要锁定。可以同步和异步调用该方法。只能同时运行一个排队操作

我不知道如何以一种有点高绩效的方式完成这项工作,请帮助:)

编辑

这是一个尝试,有人看到这种方法有任何问题吗(排除异常处理)?另外,我可以想象,与简单锁定相比,这会有相当多的开销,与使用异步委托相比,这又是如何呢

  public partial class Form1 : Form
  {
    private BlockingCollection<Task<int>> blockingCollection = new BlockingCollection<Task<int>>(new ConcurrentQueue<Task<int>>());
    private int i = 0;
    public Form1() {
      InitializeComponent();

      Task.Factory.StartNew(() =>
      {
          foreach (var task in blockingCollection.GetConsumingEnumerable()) {
            task.Start();
            task.Wait();        
          }
      });
    }


    public int Queue() {
      var task = new Task<int>(new Func<int>(DoSomething));
      this.blockingCollection.Add(task);
      task.Wait();
      return task.Result;
    }

    public int DoSomething() {
      return Interlocked.Increment(ref this.i);
    }

    private void button1_Click(object sender, EventArgs e) {
      Task.Factory.StartNew(() => Console.Write(this.Queue()));
    }


  }
公共部分类表单1:表单
{
private BlockingCollection BlockingCollection=new BlockingCollection(new ConcurrentQueue());
私有整数i=0;
公共表格1(){
初始化组件();
Task.Factory.StartNew(()=>
{
foreach(blockingCollection.GetConsumingEnumerable()中的var任务){
task.Start();
task.Wait();
}
});
}
公共int队列(){
var任务=新任务(新函数(DoSomething));
this.blockingCollection.Add(任务);
task.Wait();
返回任务。结果;
}
公共int DoSomething(){
返回联锁增量(参考此i);
}
私有无效按钮1\u单击(对象发送者,事件参数e){
Task.Factory.StartNew(()=>Console.Write(this.Queue());
}
}

TPL应该为您做这件事-只需对您的
任务调用
Wait()
-但是,如果没有阻塞,就无法做到这一点;根据定义,在您的场景中,这正是您想要做的。阻塞可以通过
锁来实现,但也有其他方法——TPL隐藏了这一点。就个人而言,在一个类似的场景中,我使用一个自定义队列和一个可以用来锁定的小型对象池(从不暴露在包装器之外)

您可能还想看看C#5异步/等待的内容

但是请注意:如果您在等待时不打算做任何有用的事情,那么最好直接在当前线程上运行该代码,除非问题是线程绑定的,例如多路复用器。如果您感兴趣,今天晚些时候(或周末),我打算发布stackoverflow用来与redis对话的多路复用器,它(至少在同步模式下)正是您所描述的问题


作为旁注;如果您可以使用回调(来自另一个线程),而不必等待完成,那么总体上效率会更高。但它并不适合所有场景。

框架中的TPL任务并行库与您的需求之间有什么差距?队列仅由框架处理,根据您的需求,有不同的同步替代方案。您可能需要查看SmartThreadPool库(),它可能适合您的需要。