Event Handler performance

前端 未结 4 575
礼貌的吻别
礼貌的吻别 2021-02-04 08:59

I have a performance problem. I create 100 new buttons and I want to assign an Click Event Handler. I execute this code for about 100 times:

Buttons[i].Button.Cl         


        
4条回答
  •  不要未来只要你来
    2021-02-04 09:37

    The code ".Click += ..." is transformed into ".add_Click( ... )". The "add_Click" method can have some logic checks.

    You can little-bit speed up with no recreation of delegate:

    EventHandler clickHandler = this.Button_Click;
    foreach(Button btn in GetButtons()) {
       btn.Click += clicHandler;
    }
    

    EDIT:

    Are you sure, the bottleneck is the attaching the handlers? I tried the for loop (100 loops) with attaching the eventhandler to Click event and I get this results:

    /* only creation the button and attaching the handler */
    button1_Click - A: 0 ms
    button1_Click - B: 0 ms
    button1_Click - A: 1 ms
    button1_Click - B: 0 ms
    button1_Click - A: 0 ms
    button1_Click - B: 0 ms
    
    /* creation the button, attaching the handler and add to the panel */
    button2_Click - A: 223 ms
    button2_Click - B: 202 ms
    button2_Click - A: 208 ms
    button2_Click - B: 201 ms
    button2_Click - A: 204 ms
    button2_Click - B: 230 ms
    

    The source code:

        void button_Click(object sender, EventArgs e) {
            // do nothing
        }
    
        private void button1_Click(object sender, EventArgs e) {
            const int MAX_BUTTONS = 100;
            var stopWatch = new System.Diagnostics.Stopwatch();
            stopWatch.Start();
            for (int i = 0; i < MAX_BUTTONS; i++) {
                var button = new Button();
                button.Click += new EventHandler(button_Click);
            }
            stopWatch.Stop();
            System.Diagnostics.Debug.WriteLine(string.Format("button1_Click - A: {0} ms", stopWatch.ElapsedMilliseconds));
    
            stopWatch.Reset();
            stopWatch.Start();
            EventHandler clickHandler = this.button_Click;
            for (int i = 0; i < MAX_BUTTONS; i++) {
                var button = new Button();
                button.Click += clickHandler;
            }
            stopWatch.Stop();
            System.Diagnostics.Debug.WriteLine(string.Format("button1_Click - B: {0} ms", stopWatch.ElapsedMilliseconds));
        }
    
        private void button2_Click(object sender, EventArgs e) {
            const int MAX_BUTTONS = 100;
    
            var stopWatch = new System.Diagnostics.Stopwatch();
    
            this.panel1.Controls.Clear();
            stopWatch.Start();
            for (int i = 0; i < MAX_BUTTONS; i++) {
                var button = new Button();
                button.Click += new EventHandler(button_Click);
                this.panel1.Controls.Add(button);
            }
            stopWatch.Stop();
            System.Diagnostics.Debug.WriteLine(string.Format("button2_Click - A: {0} ms", stopWatch.ElapsedMilliseconds));
    
            stopWatch.Reset();
    
            this.panel1.Controls.Clear();
            stopWatch.Start();
            EventHandler clickHandler = this.button_Click;
            for (int i = 0; i < MAX_BUTTONS; i++) {
                var button = new Button();
                button.Click += clickHandler;
                this.panel1.Controls.Add(button);
            }
            stopWatch.Stop();
            System.Diagnostics.Debug.WriteLine(string.Format("button2_Click - B: {0} ms", stopWatch.ElapsedMilliseconds));
        }
    

    EDIT 2: I tried compare time spent with attaching Click handler vs. attaching MouseUp handler. It does not seems, the attaching MouseUp event is faster than Click event.

    I think the problem will be somewhere else. Don't GC collect during your loop? Or don't you do something else there?

    Results:

    button1_Click - Click_A: 6 ms
    button1_Click - Click_B: 6 ms
    button1_Click - MouseUp_A: 15 ms
    button1_Click - MousUp_B: 7 ms
    
    button1_Click - Click_A: 16 ms
    button1_Click - Click_B: 7 ms
    button1_Click - MouseUp_A: 16 ms
    button1_Click - MousUp_B: 10 ms
    
    button1_Click - Click_A: 14 ms
    button1_Click - Click_B: 19 ms
    button1_Click - MouseUp_A: 27 ms
    button1_Click - MousUp_B: 5 ms
    
    button1_Click - Click_A: 17 ms
    button1_Click - Click_B: 17 ms
    button1_Click - MouseUp_A: 24 ms
    button1_Click - MousUp_B: 8 ms
    
    button1_Click - Click_A: 6 ms
    button1_Click - Click_B: 5 ms
    button1_Click - MouseUp_A: 14 ms
    button1_Click - MousUp_B: 7 ms
    
    button1_Click - Click_A: 14 ms
    button1_Click - Click_B: 9 ms
    button1_Click - MouseUp_A: 15 ms
    button1_Click - MousUp_B: 7 ms
    

    Code:

        private void button1_Click(object sender, EventArgs e) {
            const int MAX_BUTTONS = 1000;
            var stopWatch = new System.Diagnostics.Stopwatch();
    
            stopWatch.Start();
            for (int i = 0; i < MAX_BUTTONS; i++) {
                var button = new Button();
                button.Click += new EventHandler(button_Click);
            }
            stopWatch.Stop();
            System.Diagnostics.Debug.WriteLine(string.Format("button1_Click - Click_A: {0} ms", stopWatch.ElapsedMilliseconds));
    
            stopWatch.Reset();
            stopWatch.Start();
            EventHandler clickHandler = this.button_Click;
            for (int i = 0; i < MAX_BUTTONS; i++) {
                var button = new Button();
                button.Click += clickHandler;
            }
            stopWatch.Stop();
            System.Diagnostics.Debug.WriteLine(string.Format("button1_Click - Click_B: {0} ms", stopWatch.ElapsedMilliseconds));
    
            stopWatch.Start();
            for (int i = 0; i < MAX_BUTTONS; i++) {
                var button = new Button();
                button.MouseUp += new MouseEventHandler(button_MouseUp);
            }
            stopWatch.Stop();
            System.Diagnostics.Debug.WriteLine(string.Format("button1_Click - MouseUp_A: {0} ms", stopWatch.ElapsedMilliseconds));
    
            stopWatch.Reset();
            stopWatch.Start();
            MouseEventHandler mouseUpHandler = this.button_MouseUp;
            for (int i = 0; i < MAX_BUTTONS; i++) {
                var button = new Button();
                button.MouseUp += mouseUpHandler;
            }
            stopWatch.Stop();
            System.Diagnostics.Debug.WriteLine(string.Format("button1_Click - MousUp_B: {0} ms", stopWatch.ElapsedMilliseconds));
        }
    

    EDIT : The body of add_Click method (= Click += ...) is rough:

    public void add_Click(EventHandler value) {
       this.Events.AddHandler(ClickEventIdentifier, value);
    }
    

    The MouseUp events will looks similar. At least both events using Events property for holding lists of delegates for events.

    But if I tried several things I can not get the problems with the events as you wrote :(. Can you reproduce same behaviour on another computers?

提交回复
热议问题