杀死事件线程

时间:2011-06-09 14:23:11

标签: c# winforms multithreading events

我有一个每秒触发的计时器事件。有时当我退出程序时(在VS调试器中),它告诉我事件线程正在尝试访问不再存在的对象(因为主线程已经结束)。我在退出(UpdateTime.aTimer.Enabled = false;)之前尝试禁用该事件。这减少了此问题发生的次数,但有时仍会发生,因为事件会在我禁用之前触发。

  1. 这是一个严重的问题吗?如果我不处理它,Will会困扰我吗?
  2. 如果是,如何杀死它?
  3. 我问第二个问题,因为我没有引用事件线程,所以我不知道如何告诉它停止或等待它完成。

    编辑:更多背景。这是一个Winform。

    另外,我没有明确创建一个帖子。我的理解是自动创建一个线程来处理事件。

    创建计时器:

    public static void Update(){
    
        System.Timers.Timer aTimer = new System.Timers.Timer(1000);
        aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
        aTimer.Enabled = true;
    
    }
    

    事件处理程序:

    private static void OnTimedEvent(object source,ElapsedEventArgs e) {
    
        Form1obj.updateLabel(String.Format("{0}", DateTime.Now.Second),Label1);
    
    }
    

    关闭程序处理程序:

    private void Form1_FormClosing(object sender,FormClosingEventArgs e) {
    
        aTimer.Enabled = false;
    
    }
    

3 个答案:

答案 0 :(得分:3)

严重的问题?可能不是,但我不认为需要修复问题需要认真解决。例如,警告应被视为编译中的错误。此外,如果这是一个发送给客户的应用程序,在关机时显示丑陋的错误不是很专业。

如何解决这个问题取决于你如何设置线程(“事件线程”没有提供有关机制的足够信息)。一个简单的方法可能是在应用程序关闭时将主线程暂停一段时间,直到线程全部返回。您还必须在此期间停止发布新线程。

另一种可能的解决方案是处理线程的创建方式,以便关闭触发它们的进程。我想到了像ThreadPool这样的概念。在某些情况下,明确地确保线程是后台线程也可以提供帮助。

简短的回答是,如果没有您在代码中所做的事情的背景,没有人能够为您提供“这将解决您的问题”的答案。

增加:

有一些“快速,向下和肮脏”的方法来处理这个问题。没有时间进行全面分析,所以看看它们是否有效。

  1. 只需等待
  2. 即可解决错误
  3. 添加一个计数器并等待直到递增
  4. 我要考虑的第一件事是添加一个安全网,以便在关机状态下不更新标签。这与其他任何事情无关,因为这是你的错误发生的地方。我不认为“主线程不存在”是问题的核心,而是这一行:

    Form1obj.updateLabel(String.Format("{0}", DateTime.Now.Second),Label1); 
    

    如何更新不再存在的内容?是的,它在主线上,所以技术上......

    简单的等待就像:

    private void Form1_FormClosing(object sender,FormClosingEventArgs e) 
    {
         aTimer.Enabled = false;  
         Thread.Sleep(5000);
    } 
    

    隐藏表单也不错,所以用户看不到这个?

    如果您想使用更多“类似COM的方法”,您可以添加一个计数器。 Update()的增量(当事件被触发时)和OnTimedEvent()的减量。确保在更换计数器时锁定计数器,这样就不会在同一毫秒内更换两个螺纹。然后,您可以等到计数器为0以完成表单关闭或应用程序卸载。

    再次,这些是快速,向下和肮脏的方法,但它们可以帮助您避免错误。我相信有更多时间的人可以提出更优雅的解决方案。

答案 1 :(得分:1)

您可以关闭窗口as suggested in MSDN - 当您在关机处理期间将计时器设置为禁用时,设置一个标记,您的Elapsed事件处理程序可以检查以确定不再需要其他工作。< / p>

  

经过事件后可能会发生   已调用Dispose或Stop方法   或者在Enabled属性之后   设置为false,因为信号来   始终提高Elapsed事件   排队等待在线程池上执行   线。解决这场比赛的一种方法   条件   是设置一个告诉事件的标志   Elapsed事件的处理程序   忽略后续事件。

答案 2 :(得分:0)

如果问题严重与否,很难给出一个普遍的问题,这取决于计时器在做什么。它是什么样的计时器?一个系统。如何处理一个或一个UI计时器?

如果可能的话,尝试并重构您的代码,以便您可以告诉计时器停止触发,只是为了不让用户混淆错误消息。它可以像共享变量一样简单,也可以(最好)使用CancellationToken