以下代码是一个TreeView的AfterCheck事件,其中treeOwnVehicle是一个TreeView对象,请问一下:
treeOwnVehicle.AfterCheck -= treeOwnVehicle_AfterCheck;
treeOwnVehicle.AfterCheck += treeOwnVehicle_AfterCheck;
这两种写法到底是什么意思?
//下面是整体代码的大概结构
private void treeOwnVehicle_AfterCheck(object sender, TreeViewEventArgs e)
{
treeOwnVehicle.AfterCheck -= treeOwnVehicle_AfterCheck;//这真的没有参数
TreeNode currentNode = e.Node;
if (currentNode.Level == 0)
{
.....
.....
.....
}
treeOwnVehicle.AfterCheck += treeOwnVehicle_AfterCheck;
}
treeOwnVehicle.AfterCheck -= treeOwnVehicle_AfterCheck;
treeOwnVehicle.AfterCheck += treeOwnVehicle_AfterCheck;
这两种写法到底是什么意思?
//下面是整体代码的大概结构
private void treeOwnVehicle_AfterCheck(object sender, TreeViewEventArgs e)
{
treeOwnVehicle.AfterCheck -= treeOwnVehicle_AfterCheck;//这真的没有参数
TreeNode currentNode = e.Node;
if (currentNode.Level == 0)
{
.....
.....
.....
}
treeOwnVehicle.AfterCheck += treeOwnVehicle_AfterCheck;
}
-= -->减少各事件
treeOwnVehicle.AfterCheck += treeOwnVehicle_AfterCheck;
添加treeOwnVehicle的AfterCheck 事件
{
treeOwnVehicle.AfterCheck -= treeOwnVehicle_AfterCheck;//这真的没有参数
TreeNode currentNode = e.Node;
if (currentNode.Level == 0)
{
.....
.....
.....
}
treeOwnVehicle.AfterCheck += treeOwnVehicle_AfterCheck;
}
是为了在红色代码部分不会触发事件吗?
程序是逐行运行,除非if (currentNode.Level == 0)
{
.....
.....
.....
return;//跳出方法体
}再判断语句里跳出了方法体,否则还是会执行为tree添加事件的代码
treeOwnVehicle.AfterCheck += treeOwnVehicle_AfterCheck; //表示当AfterCheck 事件触发后,将会绑定执行treeOwnVehicle_AfterCheck方法。
treeOwnVehicle.AfterCheck -= treeOwnVehicle_AfterCheck // 表示当AfterCheck 事件触发后,不会执行treeOwnVehicle_AfterCheck方法。
目的明显是防止在if (currentNode.Level==0)执行过程中再一次触发treeOwnVehicle_AfterCheck事件
除非treeOwnVehicle.AfterCheck += treeOwnVehicle_AfterCheck; 可能会被跳过不执行, 否则这两句话在一起没有任何作用
这么写的意图应该是为了避免在执行 treeOwnVehicle_AfterCheck 时候 AfterCheck 再次激发, 导致再次调用 treeOwnVehicle_AfterCheck 函数, 进而造成两个 treeOwnVehicle_AfterCheck 同时执行, 导致并发同步的问题
作者意图是好的, 希望 treeOwnVehicle_AfterCheck 并发(线程)安全, 但实际的做法完全无效, 原因如下:
1. treeOwnVehicle_AfterCheck 天生不存在线程安全的隐患
2. 即使没有 1, 这样做也无法保证线程安全先说为什么不存在线程安全的隐患
windows 下的 GUI 程序, 有一个 UI 线程, 专门负责界面的处理, 比如界面绘制/刷新, 键盘/鼠标输入等
同时界面消息的激发也在这个线程中, 所以当程序激发 AfterCheck 进而调用 treeOwnVehicle_AfterCheck 时, 所有的过程都是在这个 UI 线程中进行
因为只有一个线程, 只有上一个调用结束才会进入下一个调用, 也即任何时刻最多只有一个 treeOwnVehicle_AfterCheck 会被调用, 根本不存在并发的问题再说如果存在并发的问题, 这样做为什么无法保证线程安全
作者的想法很美妙, 进入 treeOwnVehicle_AfterCheck 后, 通过 -= treeOwnVehicle_AfterCheck, 就算有另一个线程激发 AfterCheck, 因为已经解除绑定了, 也不会再调用 treeOwnVehicle_AfterCheck
但实际运行中根本行不通, 任何讲线程并发的资料, 都会提到并发的乱序, 不可预测
我举个很简单的场景说明下
假设线程A首先激发 AfterCheck, 进入了 treeOwnVehicle_AfterCheck, 按照预设目的, 需要执行 -= treeOwnVehicle_AfterCheck, 防止其他线程误入
就在准备执行, 但还没有执行时, 恰好轮到线程B执行, B 中也激发了 AfterCheck, 因为此时 A 的 -= treeOwnVehicle_AfterCheck 还没有执行, 在 B 看来, 事件绑定依然有效, 所以还是会引起 treeOwnVehicle_AfterCheck 的调用
函数中的 -= treeOwnVehicle_AfterCheck 没有起到任何帮助, 所以根本无法保证线程安全至于如何才能正确保证线程安全, 网上很多资料, 感兴趣的话可以自己了解下