【问题标题】:How to get rid of event firing boiler plate code?如何摆脱事件触发样板代码?
【发布时间】:2014-04-23 14:28:10
【问题描述】:

我正在开发一个事件驱动并运行多线程的应用程序,因此我有很多事件被触发并“以一种保存方式”触发它们,我按以下方式执行此操作:

public static void OnEVENT(EventArgs args)
{
    var theEvent = EVENT;
    if (theEvent != null)
        theEvent(this, args);
}

这种模式在我的整个应用程序中重复多次。

有没有办法摆脱这种模式的重复并以通用的方式实现它?

【问题讨论】:

  • 我个人会去掉 null 作为有效事件,并引入一个在调用时什么都不做的默认事件。
  • 我的事件每秒触发 100.000 次,“空委托解决方案”比我下面的解决方案慢...
  • 在 JIT 运行后有多少可观的量?我想看看那个基准。
  • 我没有基准测试了,但我前段时间做过......我现在才发布这个,因为我在另一个问题中被问到它。
  • 不是“真正的测试”,但在 LINQPad 中执行以下操作:pastebin.com/K1gXu4AJ => 扩展速度稍快。但是,如果您“直接”执行此操作,则速度会快两倍:pastebin.com/wDXCeLnL

标签: c# multithreading events extension-methods


【解决方案1】:

我创建了一个包含多个扩展的 Helper 类,所以我根本不需要 OnEVENT 方法,只需调用 EVENT.Raise(this, args);

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;

namespace System
{
    /// <summary>Collection of common extensions.</summary>
    public static class EventExtensions
    {
        /// <summary>Raises the specified event.</summary>
        /// <param name="theEvent">The event.</param>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The <see cref="EventArgs"/> instance containing the event data.</param>
        public static void Raise(this EventHandler theEvent, object sender, EventArgs args = null)
        {
            if (theEvent != null)
                theEvent(sender, args);
        }
        /// <summary>Raises the specified event.</summary>
        /// <typeparam name="T">The type of the event argument.</typeparam>
        /// <param name="theEvent">The event.</param>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The arguments.</param>
        public static void Raise<T>(this EventHandler<T> theEvent, object sender, T args) where T : EventArgs
        {
            if (theEvent != null)
                theEvent(sender, args);
        }
        /// <summary>Raises the specified event.</summary>
        /// <typeparam name="T">The value type contained in the EventArgs.</typeparam>
        /// <param name="theEvent">The event.</param>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The arguments.</param>
        public static void Raise<T>(this EventHandler<EventArgs<T>> theEvent, object sender, T args)
        {
            if (theEvent != null)
                theEvent(sender, new EventArgs<T>(args));
        }
        /// <summary>Raises the specified event.</summary>
        /// <typeparam name="T">The value type contained in the EventArgs.</typeparam>
        /// <param name="theEvent">The event.</param>
        /// <param name="sender">The sender.</param>
        /// <param name="newValue">The new value.</param>
        /// <param name="oldValue">The old value.</param>
        public static void Raise<T>(this EventHandler<ValueChangedEventArgs<T>> theEvent, object sender, T newValue, T oldValue)
        {
            if (theEvent != null)
                theEvent(sender, new ValueChangedEventArgs<T>(newValue, oldValue));
        }

        /// <summary>Raises the specified event for every handler on its own thread.</summary>
        /// <typeparam name="T">The value type contained in the EventArgs.</typeparam>
        /// <param name="theEvent">The event.</param>
        /// <param name="sender">The sender.</param>
        /// <param name="args">The arguments.</param>
        public static void RaiseAsync<T>(this EventHandler<EventArgs<T>> theEvent, object sender, T args)
        {
            if (theEvent != null)
            {
                var eventArgs = new EventArgs<T>(args);
                foreach (EventHandler<EventArgs<T>> action in theEvent.GetInvocationList())
                    action.BeginInvoke(sender, eventArgs, null, null);
            }
        }
    }
}

以及其中使用的ValueChangedEventArgs 类:

/// <summary>EventArgs for notifying about changed values.</summary>
/// <typeparam name="T">The type of the contained value.</typeparam>
public class ValueChangedEventArgs<T> : EventArgs
{
    /// <summary>Initializes a new instance of the <see cref="ValueChangedEventArgs{T}" /> class.</summary>
    /// <param name="newValue">The new value.</param>
    /// <param name="oldValue">The old value.</param>
    public ValueChangedEventArgs(T newValue, T oldValue)
    {
        NewValue = newValue;
        OldValue = oldValue;
    }

    /// <summary>Gets the new value.</summary>
    /// <value>The new value.</value>
    public T NewValue { get; private set; }
    /// <summary>Gets the old value.</summary>
    /// <value>The old value.</value>
    public T OldValue { get; private set; }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-31
    相关资源
    最近更新 更多