如何在C#中并行化事件处理程序执行

时间:2012-05-02 14:28:36

标签: c# multithreading parallel-processing kinect

我有一个Kinect设备,我正在使用C#开发一个程序。

为了管理设备,我使用了AllFramesReady事件来处理深度和颜色信息。

我创建了一个事件处理程序来处理名为EventHandler1的数据。我在这个事件处理程序中做了很多处理。

我想在名为EventHandler2的第二个事件处理程序中进行更多计算。

是否可以在主进程的2个不同线程上运行这2个基本上并行2个函数的事件处理程序?如果可能的话,你能给我一个代码来做这个吗?

1 个答案:

答案 0 :(得分:3)

这很容易在课堂上结束;但是,您需要在订阅所需事件之前将所有事件处理程序聚合到单个事件处理程序中。

这是一个快速而肮脏的课程来演示这一点。提供的第一个事件与事件调用一起内联,而所有其他事件在默认线程池上执行。

class ParallelEvent<TEventArg> where TEventArg : EventArgs
{
    private readonly EventHandler<TEventArg> _handler1;
    private readonly EventHandler<TEventArg>[] _moreHandlers;

    public ParallelEvent(EventHandler<TEventArg> handler1, params EventHandler<TEventArg>[] moreHandlers)
    {
        if (handler1 == null)
            throw new ArgumentNullException("handler1");
        if (moreHandlers == null)
            throw new ArgumentNullException("moreHandlers");
        _handler1 = handler1;
        _moreHandlers = moreHandlers;
    }

    public void Handler(Object sender, TEventArg args)
    {
        IAsyncResult[] asyncResults = new IAsyncResult[_moreHandlers.Length];
        for (int i = 0; i < _moreHandlers.Length; i++)
            asyncResults[i] = _moreHandlers[i].BeginInvoke(sender, args, null, null);

        _handler1(sender, args);

        for (int i = 0; i < _moreHandlers.Length; i++)
            _moreHandlers[i].EndInvoke(asyncResults[i]);
    }
}

现在使用它我们构造一个ParallelEvent类,为它提供我们想要并行运行的所有事件处理程序。然后我们使用类的Handler方法订阅事件'test'。最后,我们将事件称为“测试”并查看输出。请考虑以下示例:

private static event EventHandler<EventArgs> test;

static void Main()
{
    var e = new ParallelEvent<EventArgs>(Test1, Test2);
    test += e.Handler;
    test(null, EventArgs.Empty);
}

static void Test1(Object sender, EventArgs args)
{
    Console.WriteLine("Start Test 1");
    Thread.Sleep(100);
    Console.WriteLine("End Test 1");
}

static void Test2(Object sender, EventArgs args)
{
    Console.WriteLine("Start Test 2");
    Thread.Sleep(100);
    Console.WriteLine("End Test 2");
}

正如预期的那样,上面的程序并行运行它们,如下面的输出所示:

Start Test 1
Start Test 2
End Test 2
End Test 1

最后,您需要了解有关多线程代码的其他问题。任何现在更改的共享状态都需要同步等等。

通过一些工作,您可以调整上述类来公开事件,以便侦听器可以随意订阅和取消订阅。然后在Handler方法中,您将通过Delgate.GetInvocationList()提取委托列表。获得一个委托列表后,您可以像上面现有的Handler方法一样处理它们。