Raising events vs direct method calls differences

前端 未结 6 2062
夕颜
夕颜 2021-02-04 11:27

Raising an event, will call its event handler. eg http://msdn.microsoft.com/en-us/library/aa645739%28VS.71%29.aspx

What is the difference between using the events mechan

6条回答
  •  长情又很酷
    2021-02-04 11:57

    For anyone, who is interested in the performance of event call, I have made this simple benchmark. It shows the differences between calling a method directly, calling it via interface, via delegate and via event, where one handler is attached.

    In each scenario the method is called in corresponding way 1 000 000 000 times. Here are (maybe surprising) results:

    Delegate call: 23 240 ms - the fastest

    Event call: 23 295 ms

    Direct call: 23 396 ms

    Interface call: 23 716 ms - the slowest

    The mesurements were done in release build using C# in .NET4.0.

    The code is here:

    class Program
    {
        static void Main(string[] args)
        {
            TestClass.RunTest();
            Console.ReadLine();
        }
    }
    
    interface ITestClass
    {
        void TestMethod(object sender, TestEventArgs eventErgs);
    }
    
    class TestClass : ITestClass
    {
        #region Events
    
        event EventHandler TestEvent;
    
        #endregion
    
        #region Constructor
    
        public TestClass()
        {
            TestEvent += TestMethod;
        }
    
        #endregion
    
        #region Public Methods
    
        public static void RunTest()
        {
            int testCount = 1000000000; //1 000 000 000
    
            string format = "{0:### ### ### ##0}";
    
            #region Direct Call
    
            Console.WriteLine("Direct call");
            TestClass testClass = new TestClass();
    
            testClass.TestMethod(testClass, new TestEventArgs(3));
    
            Stopwatch stopwatch = Stopwatch.StartNew();
            for (int i = 0; i < testCount; ++i)
            {
                testClass.TestMethod(testClass, new TestEventArgs(3));
            }
            stopwatch.Stop();
            Console.WriteLine(string.Format(format, stopwatch.ElapsedMilliseconds));
            Console.WriteLine();
    
            #endregion
    
            #region Interface Call
    
            Console.WriteLine("Interface call");
            ITestClass itestClass = new TestClass();
            itestClass.TestMethod(testClass, new TestEventArgs(3));
    
            stopwatch = Stopwatch.StartNew();
            for (int i = 0; i < testCount; ++i)
            {
                itestClass.TestMethod(testClass, new TestEventArgs(3));
            }
            stopwatch.Stop();
            Console.WriteLine(string.Format(format, stopwatch.ElapsedMilliseconds));
            Console.WriteLine();
    
            #endregion
    
            #region Delegate Call
    
            Console.WriteLine("Delegate call");
            TestClass delegateTestClass = new TestClass();
            Action delegateMethod = delegateTestClass.TestMethod;
            delegateMethod(testClass, new TestEventArgs(3));
    
            stopwatch = Stopwatch.StartNew();
            for (int i = 0; i < testCount; ++i)
            {
                delegateMethod(testClass, new TestEventArgs(3));
            }
            stopwatch.Stop();
            Console.WriteLine(string.Format(format, stopwatch.ElapsedMilliseconds));
            Console.WriteLine();
    
            #endregion
    
            #region Event Call
    
            Console.WriteLine("Event call");
            TestClass eventTestClast = new TestClass();
            eventTestClast.TestEvent(testClass, new TestEventArgs(3));
    
            stopwatch = Stopwatch.StartNew();
            for (int i = 0; i < testCount; ++i)
            {
                eventTestClast.TestEvent(testClass, new TestEventArgs(3));
            }
            stopwatch.Stop();
            Console.WriteLine(string.Format(format, stopwatch.ElapsedMilliseconds));
            Console.WriteLine();
    
            #endregion
        }
    
        #endregion
    
        #region ITestClass Members
    
        public void TestMethod(object sender, TestEventArgs e)
        {
            e.Result = e.Value * 3;
        }
    
        #endregion
    }
    
    class TestEventArgs : EventArgs
    {
        public int Value { get; private set; }
    
        public int Result { get; set; }
    
        public TestEventArgs(int value)
        {
            Value = value;
        }
    }
    

提交回复
热议问题