你如何加入/中止一组动态创建的线程?

时间:2012-05-31 09:43:18

标签: c# multithreading dynamic threadabortexception

我在结束一组动态创建的线程时遇到了一些麻烦。我需要在任何给定点结束所有这些的原因是我可以刷新我的表单的某些部分并创建新的部分。下面是一个简单的场景来展示我的线程中发生的事情。

根据地点的某些变量动态创建许多线程:

 for (int i = 0; i <= mDevices.Count; i++)
        {
            ThreadStart workerThread = delegate { pollDevices(mDevices[i - 2], this); };
            new Thread(workerThread).Start();
        }

  public void pollDevices(IDeviceInterface device, DeviceManager mainUI)
    {
       System.Timers.Timer timer = null;
        if (timer == null)
        {

            timer = new System.Timers.Timer(1000);
            timer.Elapsed += delegate(object sender, ElapsedEventArgs e) { timerElapsed(sender, e, device, mainUI); };

        }
        timer.Enabled = true;

 public void timerElapsed(object sender, ElapsedEventArgs e, IDeviceInterface device, DeviceManager mainUI)
    {


         device.connect(device, this);
        //wait till thread finishes and destroy
         Thread.CurrentThread.Abort();
    }

这些线程然后处理一个计时器,并处理一个事件,处理UI更新等。但是,当我尝试刷新UI时(例如,如果数据库中的任何其他条目需要考虑),如果线程仍在运行,我会从表单上删除按钮(这些被分配给线程)中获得错误,所以之前我呼吁刷新我需要以这种方式停止所有当前线程。

所以我的问题是,在刷新UI之前,如何中止这组线程?

3 个答案:

答案 0 :(得分:2)

你有几个问题。

  • 您是closing over a loop variable
  • 您正在创建一个用于启动计时器的线程...为什么不在主线程中启动计时器?
  • 您的计时器实例没有root权限,因此在完成之前它可能有资格进行垃圾回收。
  • System.Timers.Timer事件处理程序将在ThreadPool线程上执行(至少在这种情况下),因此尝试中止其中一个线程并不会很好地结束。

这里有足够的问题,在我们回答您的主要问题之前,您将进行一些重大的重组。另外一个提示是......不要尝试从主UI线程以外的线程访问或操作任何UI元素。

答案 1 :(得分:0)

为什么在线程proc中使用计时器?

ManualResetEvent exit = new ManualResetEvent(false);
for (int i = 0; i <= mDevices.Count; i++)
    {
        ThreadStart workerThread = delegate { pollDevices(mDevices[i - 2], this, exit); };
        new Thread(workerThread).Start();
    }

public void pollDevices(IDeviceInterface device, DeviceManager mainUI, ManualResetEvent exit)
{
    while(!exit.WaitOne(1000))
    {
         // do work
         device.connect(device, this);
    }
}

然后,如果要停止所有线程,只需调用exit.Set()

答案 2 :(得分:0)

我在我的一个解决方案http://msdn.microsoft.com/en-us/magazine/cc163644.aspx

中使用了这个

这是AbortableThreadPool。可能会为你工作。

还有点混淆为什么你在一个正在完成的线程上的timerElapsed中调用Thread.Abort