【问题标题】:How can I invoke events asynchronously and sequentially?如何异步和顺序调用事件?
【发布时间】:2015-07-03 11:56:55
【问题描述】:

我有以下课程:

class Integration
{
    public event EventHandler<LogEventArgs> LogMessageEvent  

    protected virtual void OnLog(LogEventArgs e)
    {
         if(LogMessageEvent != null)
             LogMessageEvent(this, e);
    }

    public void SomeWork()
    { 
        //Do some things...

        var e = new LogMessageEvent("The file was copied...");
        OnLog(e);

        //Do more things...

        var e = new LogMessageEvent("Another thing...");
        OnLog(e);
    }
}

我需要事件订阅者不要阻止 SomeWork 方法并且执行是顺序的(“文件已复制...”事件总是首先执行)

我尝试过任务:

Task.Run(... OnLog())....

但问题在于,有时稍后创建的任务会引发一个之前创建的任务的事件。 (正如预期的那样,考虑到我没有进行同步。)

我怀疑有一些最简单的方法可以完成此任务(顺序和异步调用事件)。

【问题讨论】:

  • 类似private object _syncRoot = new object(); -> public void SomeWork() { lock(_syncRoot){ /* Do some things... */ } }?
  • 您对event 模型的依恋程度如何?因为这迫使您将其保留在 Integration 内部。外部队列可能会更好。
  • 这里的基本问题是班级试图做太多事情。
  • 嗨@HenkHolterman!我不这么认为,你能解释一下原因吗?

标签: c# multithreading events asynchronous threadpool


【解决方案1】:

存储您上次使用的Task-object 并使用ContinueWith

它告诉您的任务在第一个任务完成后继续执行新的事件调用。所以事件不是并行触发的,而是顺序触发的。

ContinueWith返回一个新的Task-object,所以你需要更新你的引用,这样下一次ContinueWith-call才能成功。

这不是线程安全的,但只要你只从一个线程调用它就可以工作(并且对我来说做得很好)。

【讨论】:

  • 这正是我所做的。但我认为我是在重新发明轮子。谢谢!
  • 恕我直言,这就是ContinueWith的目的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多