C# 如何及时停止线程?

4

我有一个用户控件,其中包含计时器。当计时器事件运行时,它将调用一些线程。

用户控件

class MyControl
{
    public Timer iTime
    {
        get;
        set;
    }

    Timer tmr;

    public MyControl
    {
    tmr = new Timer();
    }

    // Some Properties
}
}

主窗体
class MyForm
{
     Thread thd;

     MyControl cls = new MyClass();
     cls.iTime.Tick += new EventHandler(iTime_Tick);

     void iTime_Tick(object sender, EventArgs e)
     {
         thd = new Thread(delegate() { doWork(1); });
         thd.Start();

         thd = new Thread(delegate() { doOtherJob(); });
         thd.Start();
     }

     delegate void notif(int Param1);

     void Job(int Param1)
     {
         if (this.InvokeRequired) 
         {
            notif handler = new notif(notifParam);
            this.Invoke(handler, new object[] { Param1 });
         }
         else
         {
        // Other Process
         }
     }

     private void Logout()
     {
        cls.iTime.Stop();
        cls.iTime.Enabled = false;
        cls.iTime.Tick -= new EventHandler(iTime_Tick);

        thd.abort();
        thd.join();
     }
}

如何在计时器中终止线程?即使取消订阅计时器事件或关闭表单,线程仍然会运行。

3
您取消订阅事件后,您创建的线程不会停止。您将不会得到任何新的线程,但现有的线程将继续运行。您现有的代码将为每个计时器滴答声创建两个新线程,这可能会产生大量线程!这是您的意图吗? - Dan Puzey
@Dan Puzey:抱歉,我忘记了thread.Abort();和thread.Join();但即使我调用form dispose,它仍然运行。 - Blishton
1个回答

2

释放表单对您的线程没有影响。

您的代码明显不完整(例如MyControl cls = new MyClass();,我们不知道doWorkdoOtherJob是什么),但我怀疑问题的一部分是您只有一个线程变量。

每次计时器滴答声,您都会执行thd = new Thread两次。如果您的计时器滴答声十次,则thd指向您最近的线程,但可能仍有其他19个线程在运行,其中任何一个都可能使您的应用程序保持活动状态。

有一件事可能有帮助,那就是在创建的线程上明确设置.IsBackgroundtrue,因为这将鼓励它们在UI线程关闭时终止。但是,我建议以这种方式创建如此多的线程可能是一种有效的模型,您最好修正设计,只运行一个或两个工作线程,而不是启动数十个线程。


同意Dan的观点。当您启动第二个线程并将其分配给thd时,您会失去对thd的第一个引用,因此无法中止它。线程是函数调用(您的doWork和doOtherJob),当函数结束时,线程也会结束。终止线程的正确方法是使用哨兵变量来控制其执行,可以将其传递到函数委托中或作为共享局部变量。您必须在线程委托中不断检查哨兵,并在设置时退出。 - Sean B
如果我在计时器中创建新的线程实例(thdSecond = new thread(delegate() { doWork(1);)),它是否可追踪并且可以被Abort()? - Blishton
是的,但当你的计时器再次触发时,你会覆盖它,而且你将无法中止它。 - Dan Puzey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接