合并从线程抛出事件的C#代码

时间:2015-03-18 15:19:53

标签: c# multithreading

我有一个线程网络类,我需要在不同情况下抛出事件。异步抛出事件的代码如下所示:

    void FireCreateRoomRequestReceived(CreateRoomRequestArguments arguments)
    {
        if (CryptSetupReceived == null)
            return;

        _AysncManager.Post(new SendOrPostCallback(delegate(object obj)
        {
            CreateRoomRequestReceived(this, arguments);
        }), null);
    }

    void FireInviteToRoomRequestReceived(InviteToRoomRequestArguments arguments)
    {
        if (InviteToRoomRequestReceived == null)
            return;

        _AysncManager.Post(new SendOrPostCallback(delegate(object obj)
        {
            InviteToRoomRequestReceived(this, arguments);
        }), null);
    }

    void FireMessageContentReceived(MessageContentArguments arguments)
    {
        if (MessageContentReceived == null)
            return;

        _AysncManager.Post(new SendOrPostCallback(delegate(object obj)
        {
            MessageContentReceived(this, arguments);
        }), null);
    }

我的问题是,如果我能以某种方式整合这样的代码。我不知道我会怎么做。

1 个答案:

答案 0 :(得分:1)

在我看来,你可以解决你的整合问题。问题,以及线程安全问题,通过实现一个简单的扩展方法来处理您的事件。这实际上是一种相当常见的技术:

static class Extensions
{
    public static void Raise<T>(this EventHandler<T> handler, object sender, T args)
    {
        if (handler != null)
        {
            handler(sender, args);
        }
    }
}

请注意,要执行此操作,您必须确保将事件声明为EventHandler<T>类型。 E.g:

public event EventHandler<CreateRoomRequestArguments> CryptSetupReceived;
public event EventHandler<InviteToRoomRequestArguments> InviteToRoomRequestReceived;
public event EventHandler<MessageContentArguments> MessageContentReceived;

上述扩展方法只会引发事件。在你的情况下,你想要使用的地方(显然......你遗漏了声明,所以我们必须依赖推理)一个SynchronizationContext对象来异步调用处理程序,你可以这样做:

public static void RaiseAsync<T>(this EventHandler<T> handler,
    object sender, T args, SynchronizationContext context)
{
    if (handler != null)
    {
        context.Post(o => handler(sender, args), null);
    }
}

要实际使用这些方法,只需在感兴趣的事件中调用它们即可。 E.g:

MessageContentArguments messageContentArguments = ...; // init as appropriate

MessageContentReceived.RaiseAsync(this, messageContentArguments, _AsyncManager);