在C#中升级 [英] RaiseEvent in C#

查看:154
本文介绍了在C#中升级的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(我知道标题听起来很简单,但坚持下来,这可能不是你认为的问题。)

(I know the title sounds easy, but hold on—this probably isn't the question you think it is.)

在VB.NET中,我能够编写自定义事件。例如,我有一个单独的线程会定期引发一个事件,在这种情况下,GUI需要更新。我不想让忙线程打扰UI计算,我不想把Me.Invoke(Sub()...)放在事件处理程序中,因为它也是从GUI线程调用的。

In VB.NET I was able to write custom events. For an example, I had a separate thread that would periodically raise an event and on that event the GUI would need to be updated. I didn't want the busy thread to bother with UI calculations and I didn't want to put Me.Invoke(Sub() ...) in the event handler since it was also called from the GUI thread.

我想出了这个非常有用的一些代码。 GUI线程将设置EventSyncInvoke = Me(主窗体)。然后,线程可以像往常一样简单地提高事件TestEvent,没有特殊的代码,它将在GUI线程上无缝执行:

I came up with this very useful bit of code. The GUI thread would set EventSyncInvoke = Me (the main form). The thread could then simply raise the event TestEvent as usual, no special code, and it would be seamlessly executed on the GUI thread:

Private TestEventDelegate As EventHandler
Public EventSyncInvoke As System.ComponentModel.ISynchronizeInvoke

Public Custom Event TestEvent As EventHandler
    AddHandler(value As EventHandler)
        TestEventDelegate = [Delegate].Combine(TestEventDelegate, value)
    End AddHandler

    RemoveHandler(value As EventHandler)
        TestEventDelegate = [Delegate].Remove(TestEventDelegate, value)
    End RemoveHandler

    RaiseEvent(sender As Object, e As System.EventArgs)
        If EventSyncInvoke IsNot Nothing Then
            EventSyncInvoke.Invoke(TestEventDelegate, {sender, e})
        Else
            TestEventDelegate.Invoke({sender, e})
        End If
    End RaiseEvent
End Event

现在在C #我可以做到这一点:

Now in C# I can do this much:

public event EventHandler TestEvent
    add
    {
        testEventDelegate = (EventHandler)Delegate.Combine(testEventDelegate, value);
    }
    remove
    {
        testEventDelegate = (EventHandler)Delegate.Remove(testEventDelegate, value);
    }


}

但是

编辑:

其他答案告诉我事实上,我无法直接在C#中执行,但不是为什么我不能,为什么我不想要的理由。我花了一段时间来了解C#事件如何与VB.NET进行比较。对于没有把握好的人,开始思考正确的路线,我留下了我自己的说明

老实说,我习惯了样板OnTestEvent格式,我不太喜欢让它与其他帮助方法不同的想法。 :-)现在我明白了理由,我看到它实际上是放这个东西的最好的地方。

Honestly, I was so used to the boilerplate OnTestEvent format that I didn't quite like the idea of making it different from the rest of the helper methods. :-) Now that I understand the rationale, I see that it is actually the best place to put this stuff.

推荐答案

VB .NET允许您隐藏使用RaiseEvent关键字调用代理的背景详细信息。 RaiseEvent调用事件委托或自定义RaiseEvent部分进行自定义事件。

VB.NET allows you to hide the background details of calling the delegates with the RaiseEvent keyword. RaiseEvent calls either the event delegate or your custom RaiseEvent section for a custom event.

在C#中,没有RaiseEvent。举办活动是基本上,不仅仅是呼叫一个委托。当您正在做的所有提升它都是调用委托时,没有任何自定义的RaiseEvent部分可以被无缝地调用。所以对于C#,自定义事件就像骨架,实现添加和删除事件,但不能实现提升它们的能力。这就像将所有的RaiseEvent TestEvent(sender,e)替换为自定义RaiseEvent部分中的代码。

In C#, there is no RaiseEvent. Raising an event is basically no more than calling a delegate. No custom RaiseEvent sections can be seamlessly called when all you're doing to raise it is calling a delegate. So for C#, custom events are like skeletons, implementing add and remove for events but not implementing the ability to raise them. It's like having to replace all your RaiseEvent TestEvent(sender, e) with the code from the custom RaiseEvent section.

对于一个普通的事件,大概就像NormalEvent ,e)。但是,一旦你放入一个自定义的添加和删除,你必须使用添加和删除中使用的任何变量,因为编译器不再这样做了。这就像VB.NET中的自动属性:一旦手动放入getter和setter,你必须声明并处理你自己的局部变量。所以代替TestEvent(sender,e),使用testEventDelegate(sender,e)。那就是你重新路线的事件代表。






我比较了从VB.NET到C#的移动,不得不用您的自定义RaiseEvent代码替换每个RaiseEvent。 RaiseEvent代码部分基本上是一个事件和一个帮助函数。实际上,在一个受保护的OnTestEvent方法中,VB.NET或C#中只有一个RaiseEvent实例是标准的,并将该方法调用举起事件这允许任何具有访问受保护(或私有或公开)OnTestEvent的代码来引发事件。对于你想要做的,只需将它放在方法中更容易,更简单,更好地执行 。这是最好的做法。

For a normal event, raising looks roughly like NormalEvent(sender, e). But as soon as you put in a custom add and remove, you must use whatever variable you used in the add and remove because the compiler isn't doing it anymore. It's like automatic properties in VB.NET: once you put in a getter and setter manually, you have to declare and handle your own local variable. So instead of TestEvent(sender, e), use testEventDelegate(sender, e). That's where you rerouted the event delegates.


I compared moving from VB.NET to C# with having to replace each of your RaiseEvents with your custom RaiseEvent code. A RaiseEvent code section is basically an event and a helper function rolled together. It's actually standard to only have one instance of a RaiseEvent in either VB.NET or C# inside a protected OnTestEvent method and call that method to raise the event. This allows any code with access to the protected (or private or public) OnTestEvent to raise the event. For what you want to do, just putting it in the method is easier, simpler and performs slightly better. This is best practice.

现在,如果你真的想要(或需要)以某种方式模仿VB.NET的RaiseEvent灰色隐藏调用SomeDelegate(sender,e)并有魔法发生,你可以简单地隐藏第二代表中的nitty-gritty:

Now if you really want to want (or need) somehow to mimic VB.NET's RaiseEvent nitty-gritty-hiding call SomeDelegate(sender, e) and have the magic happen, you can simply hide the nitty-gritty inside a second delegate:

NiceTestEvent = (sender, e) => eventSyncInvoke.Invoke(testEventDelegate, new object[] { sender, e });

现在可以调用NiceTestEvent(sender,e)。您将无法调用TestEvent(sender,e)。 TestEvent只适用于通过Visual Studio将告诉您的外部代码添加和删除。

Now you can call NiceTestEvent(sender, e). You won't be able to call TestEvent(sender, e) though. TestEvent is only for outside code to add and remove through, as Visual Studio will tell you.

这篇关于在C#中升级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆