如何在C#和TPL中并行处理事件

Weg*_*ged 1 c# parallel-processing events delegates task-parallel-library

我有一个事件,当被解雇时,订阅者执行一些可能需要一段时间才能返回的数据库代码.我想并行执行所有订阅者委托.我正在尝试使用Parallel.Foreach,但我无法得到任何建议吗?

我目前正在尝试沿着这些方向做点什么.

Parallel.ForEach(FacilitiesChanged.GetInvocationList(),某种lambda表达式)

其中FacilitiesChanged是一个事件.

Ree*_*sey 5

我有一个事件,当被解雇时,订阅者执行一些可能需要一段时间才能返回的数据库代码.我想并行执行所有订阅者委托.我正在尝试使用Parallel.Foreach,但我无法得到任何建议吗?

我建议将并行性推送到订阅者端,而不是尝试并行调用委托.

让订阅者做:

private void OnMyEvent(object sender, EventArgs e)
{
     Task.Factory.StartNew( () => 
     {
          // Your DB code logic here...
     });
}
Run Code Online (Sandbox Code Playgroud)

这将导致事件异步发生.

如果你必须等待返回类型,我个人会一起避免事件.这里的问题是事件订户不会阻止固有的期望.允许事件阻止将违反预期,并导致问题.

相反,我建议使用一种控制反转形式,并通过接口而不是事件来处理.然后,与标准事件使用情况相比,观察者模式的变化有所不同:

// Publisher side - add methods to add/remove "subscribers":
public void AddListener(IDatabaseOperation op)   
{
    lock(syncObj)  // thread safety may be an issue...
        this.listeners.Add(op); 
}

private void OnEvent()
{
    lock(syncObj)
    {
        Parallel.ForEach(this.listeners, l => l.DoOperation());
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您必须在发布端多线程调用您的调用,可以通过以下方式完成:

private void RaiseMyEvent(MyEventArgs e)
{
    var handler = this.TheEvent;

    if (handler != null)
    {
        var tasks = new List<Task>();
        foreach(var yourEvent in handler.GetInvocationList().Cast<EventHandler<MyEventArgs>())
            tasks.Add(Task.Factory.StartNew( () => yourEvent(this, e)));

        // Optionally wait here...  Removing the following makes this asynchronous
        Task.WaitAll(tasks.ToArray());
    }
}
Run Code Online (Sandbox Code Playgroud)