事件处理程序的处理顺序问题
2010-03-13 19:15
423 查看
这也是今天讨论到的一个话题,其实还是比较简单的。因为事件处理程序都是在主线程被执行的,所以主线程肯定是依次执行他们。那么究竟是什么决定了这个顺序呢?
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
其实要深入看的话,这是因为事件的处理程序是通过一个列表来管理的,就是EventHandlerList
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
为什么使用EventHandlerList?这个问题之前就谈论过,默认情况下,客户端程序每为事件绑定一个处理程序,就需要在类型中产生一个delegate的引用,如此一来,如果事件很多的话,不利于较好地控制内存。但如果用EventHandlerList的话,则有利于统一管理所有的delegate
usingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Text; usingSystem.Reflection; usingSystem.Threading; namespaceConsoleApplication1 { classProgram { staticvoidMain(string[]args) { ///这个例子解释了如果为一个事件绑定了多个事件处理程序,那么他们处理的顺序与绑定顺序是一致的 Console.WriteLine("主线程号是:{0}",Thread.CurrentThread.ManagedThreadId); Employeee=newEmployee(); e.NameChanged+=newEventHandler(e_NameChanged); e.NameChanged+=newEventHandler(e_NameChanged2); e.Name="areschen"; Console.Read(); } staticvoide_NameChanged2(objectsender,EventArgse) { Console.WriteLine("第2个事件处理程序触发的时间是:{0}",DateTime.Now); Console.WriteLine("当前线程号是:{0}",Thread.CurrentThread.ManagedThreadId); } staticvoide_NameChanged(objectsender,EventArgse) { Console.WriteLine("第1个事件处理程序触发的时间是:{0}",DateTime.Now); Console.WriteLine("当前线程号是:{0}",Thread.CurrentThread.ManagedThreadId); } } classEmployee { publiceventEventHandlerNameChanged; privatestringname; publicstringName { get { returnname; } set { name=value; if(NameChanged!=null) NameChanged(this,null); } } } }
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
其实要深入看的话,这是因为事件的处理程序是通过一个列表来管理的,就是EventHandlerList
[HostProtection(SecurityAction.LinkDemand,SharedState=true)] publicsealedclassEventHandlerList:IDisposable { //Fields privateListEntryhead; privateComponentparent; //Methods publicEventHandlerList() { } internalEventHandlerList(Componentparent) { this.parent=parent; } publicvoidAddHandler(objectkey,Delegatevalue) { ListEntryentry=this.Find(key); if(entry!=null) { entry.handler=Delegate.Combine(entry.handler,value);//这里的关键在于Delegate.Combine,所以根据注册顺序不一样,是一个顺序型的组合 } else { this.head=newListEntry(key,value,this.head); } } publicvoidAddHandlers(EventHandlerListlistToAddFrom) { for(ListEntryentry=listToAddFrom.head;entry!=null;entry=entry.next) { this.AddHandler(entry.key,entry.handler); } } publicvoidDispose() { this.head=null; } privateListEntryFind(objectkey) { ListEntryhead=this.head; while(head!=null) { if(head.key==key) { returnhead; } head=head.next; } returnhead; } publicvoidRemoveHandler(objectkey,Delegatevalue) { ListEntryentry=this.Find(key); if(entry!=null) { entry.handler=Delegate.Remove(entry.handler,value); } } //Properties publicDelegatethis[objectkey] { get { ListEntryentry=null; if((this.parent==null)||this.parent.CanRaiseEventsInternal) { entry=this.Find(key); } if(entry!=null) { returnentry.handler; } returnnull; } set { ListEntryentry=this.Find(key); if(entry!=null) { entry.handler=value; } else { this.head=newListEntry(key,value,this.head); } } } //NestedTypes privatesealedclassListEntry { //Fields internalDelegatehandler; internalobjectkey; internalEventHandlerList.ListEntrynext; //Methods publicListEntry(objectkey,Delegatehandler,EventHandlerList.ListEntrynext) { this.next=next; this.key=key; this.handler=handler; } } } 所以,既然是通过线性表来保存的,那么就有一个先后顺序的情况。其实,一个更好的写法是下面这样的
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Reflection;
usingSystem.Threading;
usingSystem.ComponentModel;
namespaceConsoleApplication1
{
classProgram
{
staticvoidMain(string[]args)
{
///这个例子解释了如果为一个事件绑定了多个事件处理程序,那么他们处理的顺序与绑定顺序是一致的
Console.WriteLine("主线程号是:{0}",Thread.CurrentThread.ManagedThreadId);
Employeee=newEmployee();
e.NameChanged+=newEventHandler(e_NameChanged);
e.NameChanged+=newEventHandler(e_NameChanged2);
e.Name="areschen";
Console.Read();
}
staticvoide_NameChanged2(objectsender,EventArgse)
{
Console.WriteLine("第2个事件处理程序触发的时间是:{0}",DateTime.Now);
Console.WriteLine("当前线程号是:{0}",Thread.CurrentThread.ManagedThreadId);
}
staticvoide_NameChanged(objectsender,EventArgse)
{
Console.WriteLine("第1个事件处理程序触发的时间是:{0}",DateTime.Now);
Console.WriteLine("当前线程号是:{0}",Thread.CurrentThread.ManagedThreadId);
}
}
classEmployee
{
//publiceventEventHandlerNameChanged;
protectedEventHandlerListlistEventDelegates=newEventHandlerList();
privateobjectNameChangedEventKey=newobject();
publiceventEventHandlerNameChanged{
add{
listEventDelegates.AddHandler(NameChangedEventKey,value);
}
remove{
listEventDelegates.RemoveHandler(NameChangedEventKey,value);
}
}
privatestringname;
publicstringName
{
get
{
returnname;
}
set
{
name=value;
if(listEventDelegates[NameChangedEventKey]!=null){
listEventDelegates[NameChangedEventKey].DynamicInvoke(newobject[]{this,null});
}
}
}
}
}
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
为什么使用EventHandlerList?这个问题之前就谈论过,默认情况下,客户端程序每为事件绑定一个处理程序,就需要在类型中产生一个delegate的引用,如此一来,如果事件很多的话,不利于较好地控制内存。但如果用EventHandlerList的话,则有利于统一管理所有的delegate
相关文章推荐
- 事件处理程序的处理顺序问题
- Sharepoint列表事件处理程序有小问题。
- Netty长连接的事件处理顺序问题
- 用事件队列解决GUI的操作顺序问题(Qt中处理方法)
- 使用欢迎使用事件处理程序向导的问题
- JavaScript将DOM事件处理程序封装为event.js 出现的低级错误问题
- 跨浏览器解决事件处理程序兼容问题
- 原生js解决对象事件处理程序添加和删除的兼容性问题
- Netty长连接的事件处理顺序问题
- JavaScript权威指南_168_第17章_事件处理_17.3-调用事件处理程序-返回值、调用顺序
- Netty长连接的事件处理顺序问题
- this指向问题——严格、非严格模式,事件处理程序
- Android中事件分发处理MotionEvent事件在onInterceptTouchEvent()、onTouchEvent()中的传递顺序【转】
- MFC程序的消息处理顺序
- 编程常见问题记录:明明有响应按钮的事件,但程序就是无法捕获到
- MFC程序中消息以及函数的处理顺序简介
- 按钮事件处理程序
- WSS3SDK之:如何创建一个事件处理程序Feature
- Java 组件及事件处理实训 实训2:编写一个窗体程序,用于计算一元二次方程
- 由Ajax请求一般处理程序下载文件引发的问题后的一些总结