事件处理程序性能 [英] Event Handler performance
问题描述
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屋!