【问题标题】:How to parallelize event handler execution in C#如何在 C# 中并行化事件处理程序执行
【发布时间】:2012-05-02 14:28:36
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 如果你可以把你的代码放到线程中,你可以使用这个msdn.microsoft.com/en-us/library/7a2f3ay4(v=vs.80).aspx
  • 问题是我在两个事件处理程序上都做了很多计算,我不想等待第一个处理程序结束,以便我可以开始执行第二个处理程序。我想同时运行它们。
  • Task.Factory.StartNew(() => Console.WriteLine("aaa"));
  • 能否详细说明 Task.Factory.StartNew() 是什么意思?我如何将这个东西应用到事件处理程序执行中?
  • @Simon 将Console.WriteLine 替换为您要在线程中执行的代码。

标签: c# multithreading parallel-processing kinect


【解决方案1】:

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

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

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 方法一样处理它们。

【讨论】:

    猜你喜欢
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 2011-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-12
    • 2014-03-14
    相关资源
    最近更新 更多