更新时间:2023-02-27 15:12:26
代码.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?