AutoResetEvent 的诡异行为

简介: 一.缘起        最近做一个服务端程序,系统运行时,在特定的时候会启动一个通知线程,通知线程执行的方法经简化后就是如下的FirstStateNotifyThread: AutoResetEvent autoResetEvent = new AutoResetEvent(fal...

 一.缘起

       最近做一个服务端程序,系统运行时,在特定的时候会启动一个通知线程,通知线程执行的方法经简化后就是如下的FirstStateNotifyThread:

    AutoResetEvent autoResetEvent = new AutoResetEvent(false);
    private void FirstStateNotifyThread()
    {
        this.logger.LogWithTime("进入通知线程");            
        if (this.autoResetEvent.WaitOne(this.timeoutInMsecs))
        {
            //......
        }
        else
        {
            //......
        }
    }

      通知线程中用到了AutoResetEvent以等待某个事件完成以达到同步的目的。启动线程的方法如下:

   CbGeneric cb = new CbGeneric(this.FirstStateNotifyThread);
   cb.BeginInvoke(null, null);

      开发、调试、测试、部署到自己的测试服务器 都一切运行正常。当部署到正式的服务器上运行时,发现需要启动线程的时刻到来时,没有出现“进入通知线程”的日志,即FirstStateNotifyThread方法没有被执行,线程没有被启动。

 

二.追踪

      于是,我换了一种启动线程的方式,像下面这样:

   Thread thread = new Thread(new ThreadStart(this.FirstStateNotifyThread));
   thread.Start();

      情况不仅依旧,而且当要启动线程时,整个进程异常退出了,弹出的提示框内容是“程序遇到问题,将被关闭”。

      然后,我再换一种方式:

   ThreadPool.QueueUserWorkItem(new WaitCallback(this.FirstStateNotifyThread1) ;

      仍然一样,也导致进程退出。
      郁闷了,并且只有这台服务器上才会出现,其也是windows 2003 server 系统,是怎么回事了?

      接着,我把FirstStateNotifyThread 方法中的逻辑代码全部去掉,只留一句写日志的代码,结果,可以正常执行。就这样不断地增加业务代码,最后问题定位到了autoResetEvent.WaitOne方法,如果注释掉这一句,就OK,开启这一句,就导致执行FirstStateNotifyThread 的线程无法启动。

      大概找到问题的位置后,我尝试使用AutoResetEvent的另一个WaitOne重载方法:

  autoResetEvent.WaitOne(this.timeoutInMsecs ,false)

      使用这个重载方法后,在正式的服务器上也可以顺利的启动FirstStateNotifyThread 线程了。

 

三.暂时的结论

      问题看似解决了,但是问题的根源在哪里了?我用reflector查看了AutoResetEvent的WaitOne方法的源码,一起来看看:

[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public virtual bool WaitOne(int millisecondsTimeout)
{
    return this.WaitOne(millisecondsTimeout, false);
}

public virtual bool WaitOne(int millisecondsTimeout, bool exitContext)
{
    if (millisecondsTimeout < -1) throw new ArgumentOutOfRangeException("millisecondsTimeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
    return this.WaitOne((long) millisecondsTimeout, exitContext);
}

      第一个WaitOne方法直接调用了第二个重载的WaitOne方法,这没什么问题。焦点在于第一个WaitOne方法标记了TargetedPatchingOptOut这样一个Attribute,查询MSDN知道:TargetedPatchingOptOut是用于指示内联(inline),熟悉C或C++的朋友对这个词应该非常熟悉。根据前面的步步验证,可以肯定的是,在我们正式的服务器上要加载或执行内联了WaitOne的代码镜像时,出现了异常。至于是什么异常,代码中使用try/catch捕获不到。

      之后,我又测试了ManualResetEvent,也存在同样的情况。问题的根源可能已经涉及到了CLR或windows程序执行,但还是可以总结一点经验:为了使ManualResetEvent/AutoResetEvent在所有的机器上都能正常运转,请使用带有两个参数的WaitOne方法。

      有哪位朋友能知道更多内幕原因的,还望留言不吝赐教,谢谢。 

 

目录
相关文章
计算机中存储单位的换算
计算机中存储单位的换算
|
网络协议 网络性能优化 算法
iptables深入解析-mangle篇
      讲了filter、ct、nat 现在剩下最后一个知名模块mangle,但是自身虽然知道内核支持修改数据包的信息,它主要用在策略路由和qos上.我们就具体分析一下.      mangle表主要用于修改数据包的TOS(Type Of Service,服务类型)、TTL(T...
8495 0
|
索引
【Flutter 开发必备】AzListView 组件全解析,打造丝滑索引列表!
在 Flutter 开发中,AzListView 是实现字母索引分类列表的理想选择。它支持 A-Z 快速跳转、悬浮分组标题、自定义 UI 和高效性能,适用于通讯录、城市选择等场景。本文将详细解析 AzListView 的核心参数和实战示例,助你轻松实现流畅的索引列表。
832 7
|
JSON Java fastjson
Java日志通关(五) - 最佳实践
作者日常在与其他同学合作时,经常发现不合理的日志配置以及五花八门的日志记录方式,后续作者打算在团队内做一次Java日志的分享,本文是整理出的系列文章第五篇。
|
机器学习/深度学习 人工智能 物联网
探索软件测试的前沿技术与未来趋势
在数字化时代的浪潮中,软件测试作为保障软件质量的重要环节,正经历着前所未有的变革。本文将深入探讨当前软件测试领域的最新技术进展,包括自动化测试、人工智能在测试中的应用、以及云测试平台的发展等。同时,文章也将对软件测试的未来发展趋势进行预测,为读者揭示一个更加智能化、高效化的软件测试新时代。
LabVIEW中不同颜色连线的含义
LabVIEW中不同颜色连线的含义
699 2
|
传感器 存储 监控
什么是智慧工地?智慧工地管理平台有哪些功能?
智慧工地的智能化现场信息管理,减少人力物力的投入,加快了施工进度,能够缩短工期,提升经济效益。
5384 3
|
机器学习/深度学习 人工智能 算法
AI与未来医疗:重塑健康产业的双刃剑
本文深入探讨了人工智能(AI)在医疗健康领域中的应用与前景。从AI的基础性应用如智能诊断、药物研发,到其在远程医疗、个性化治疗和患者管理中的角色,文章详细分析了AI技术如何提高医疗服务效率、降低错误率并增强患者体验。同时,文章也讨论了AI在医疗领域面临的伦理、隐私和安全挑战,以及解决这些挑战的可能路径。最后,本文展望了AI与人类医生合作的未来图景,强调了技术与人文关怀结合的重要性。
243 9
|
监控 安全 网络安全
云中守护者:云计算时代的网络安全挑战与应对策略
【8月更文挑战第15天】在数字化浪潮的推动下,云计算已成为现代企业信息技术架构的核心。然而,随着云服务的广泛应用,网络安全威胁也随之增多,对信息安全管理提出了新的要求。本文将探讨云计算环境下的网络安全挑战,分析云服务模式对安全策略的影响,并提出有效的应对措施,以期为企业在享受云计算带来的便利的同时,保障数据和网络的安全。