事件处理程序性能 [英] Event Handler performance

查看:114
本文介绍了事件处理程序性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个性能问题。我创建了100个新的按钮,我想分配一个点击事件处理程序。我执行这个代码约100次:

  Buttons [i] .Button.Click + = new System.EventHandler(Button_Click) ; 

需要大约2秒才能完成。我在同一个函数中有很多其他的事件赋值,但是它们只需要几毫秒来执行。所以我已经转换了我的代码

  Buttons [i] .Button.MouseUp + = new System.Windows.Forms.MouseEventHandler Button_Click); 

现在的代码很快(有些毫秒,像其他的)。显然,我修改了Button_click函数的参数以适应新的事件需求,但没有其他更改。



我想知道为什么会发生这种情况。 EventHandler慢吗?还是我做错了?还是有最佳做法?



我正在使用VC2010与C#,在Windows窗体应用程序中使用.NET 4。



编辑:



现在我已经缩小我的代码,我把它放在那里:

 秒表stopWatch =新的秒表(); 
stopWatch.Start();
按钮b;
for(n = 0; n <100; n ++)
{
b = new Button();
b.Location = new System.Drawing.Point(100,0);
b.Name =btnGrid;
b.Size = new System.Drawing.Size(50,50);
b.Text = b.Name;
b.UseVisualStyleBackColor = true;
b.Visible = false;
b.Text =..;
b.Click + = new EventHandler(this.Button_Click);
//b.MouseUp + = new System.Windows.Forms.MouseEventHandler(this.Button_ClickUP);
}
stopWatch.Stop();

TimeSpan ts = stopWatch.Elapsed;
string elapsedTime = String.Format({0:00}:{1:00}:{2:00}。{3:00},ts.Hours,ts.Minutes,ts.Seconds,ts .Milliseconds / 10);
Log(elapsedTime,Color.Purple);

Button_Click和Button_Click是:

  private void Button_Click(object sender,EventArgs e)
{
}

private void Button_ClickUP(object sender,MouseEventArgs e)
{
}

我把这段代码放在一个按钮中,日志功能显示导致备忘录。当我启用点击结果是01.05秒,但是当我启用MouseUp结果是00.00。



差异 - > ONE SECOND!



为什么??



==编辑==



我用.NET Framework 4. VS2010。 Win XP。我发现这一点:如果我使用.NET 3.5或更低的速度变化:0.5秒。一半
如果我在调试或发布模式下编译它不会改变。



如果我使用可执行文件,而没有调试器是快速的。 strong>



所以我更改了我的问题:.NET 4慢于.NET 3?为什么发布模式与独立版本不同?



非常感谢。

解决方案

代码.Click + = ...被转换为.add_Click(...)。 add_Click方法可以进行一些逻辑检查。



您可以稍微加快一点,不需要代理娱乐:

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

编辑:



你确定,瓶颈是附加处理程序吗?
我尝试使用for循环(100循环),将事件处理程序附加到Click事件,我得到这个结果:

  / *只创建按钮并附加处理程序* / 
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

/ *创建按钮,附加处理程序并添加到面板* /
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

源代码:

  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(); (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; (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(); (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; (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));
}

编辑2:
我试过比较附加Click处理程序与附加MouseUp处理程序所花费的时间。似乎没有,附加的MouseUp事件比Click事件更快。



我认为问题会在别的地方。 GC循环中不要收集GC?或者你不在别的地方做些什么?



结果:

  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

代码:

  private void button1_Click对象发件人,EventArgs e){
const int MAX_BUTTONS = 1000;
var stopWatch = new System.Diagnostics.Stopwatch();

stopWatch.Start(); (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; (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(); (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; (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));
}

编辑:
add_Click 方法(= 点击+ = ... )粗糙:

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

MouseUp事件看起来会相似。至少两个事件使用事件属性来保存事件的代理列表。



但是,如果我尝试了几件事情($)
您可以在另一台电脑上再现相同的行为吗?


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.Click += new System.EventHandler(Button_Click);

It takes about 2sec to complete. I have a lot of other event assignments in the same function, but they all take only some millisecond to execute. So I have transformed my code in

Buttons[i].Button.MouseUp += new System.Windows.Forms.MouseEventHandler(Button_Click);

Now the code is fast (some millisecond, like the others). Obviously I have modified the parameters of the function "Button_click" to fit the new event requirements, but no other changes were made.

I am wondering why this could happen. Is EventHandler that slow? Or am I doing something wrong? Or is there a best practice?

I am using VC2010 with C#, using .NET 4 in a Windows Form application.

EDIT:

Now I have "minified" my code and I put it there:

            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
            Button b;
            for(n=0;n<100;n++)
            {
                b = new Button();
                b.Location = new System.Drawing.Point(100, 0);
                b.Name = "btnGrid";
                b.Size = new System.Drawing.Size(50, 50);
                b.Text = b.Name;
                b.UseVisualStyleBackColor = true;
                b.Visible = false;
                b.Text = "..";
                b.Click += new EventHandler(this.Button_Click);
                //b.MouseUp += new System.Windows.Forms.MouseEventHandler(this.Button_ClickUP);
            }
            stopWatch.Stop();

            TimeSpan ts = stopWatch.Elapsed;
            string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);
            Log(elapsedTime, Color.Purple);

Button_Click and Button_Click are:

    private void Button_Click(object sender, EventArgs e)
    {            
    }

    private void Button_ClickUP(object sender, MouseEventArgs e)
    {
    }

I put this code in a button and the "Log" function display the result in a memo. When I enable "Click" the result is 01.05 sec, but when I enable "MouseUp" the result is 00.00.

Difference -> ONE SECOND!

why!?

== EDIT ==

I use .NET Framework 4. VS2010. Win XP. I found this: if I use .NET 3.5 or lower the speed changes: 0.5 sec. An Half. If I compile in debug or release mode it doesn't change.

If I use the executable without the debugger is blazing fast.

So I change my question: is .NET 4 slower then .NET 3? Why the Release mode works differently compared to the stand alone version?

Many thanks.

解决方案

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?

这篇关于事件处理程序性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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