停止由foreach创建的线程

时间:2012-03-10 14:46:29

标签: c# .net

好吧,我创建了一个循环,创建了很多线程,请参阅:

foreach (DataGridViewRow dgvRow in dataGridView1.Rows)
{

    Class h = new Class(dgvRow.Cells["name"].Value.ToString());

    Thread trdmyClass = new Thread(h.SeeInfoAboutName);
    trdmyClass.IsBackground = true;
    trdmyClass.Start();
}

这样可以正常工作,创建我需要的线程,但我希望在我点击一个按钮时,一次性停止所有这些线程(使用Thread.Abort()) 我怎么能这样做?

3 个答案:

答案 0 :(得分:3)

我不会使用Thread.Abort。它可能会产生一些非常令人讨厌的后果。您应该做的是通过将它们放入列表中来跟踪您创建的线程。然后,您可以使用ManualResetEvent类。线程应检查是否定期引发重置,如果已设置,则应清除并退出。我使用WaitOne方法将毫秒超时,然后检查返回值以允许线程在循环中运行。如果返回true,则设置信号,您可以退出循环或从线程返回。如果你使用的是.Net 4,你也可以使用CancelationToken。

http://msdn.microsoft.com/en-us/library/system.threading.manualresetevent.aspx

http://msdn.microsoft.com/en-us/library/system.threading.cancellationtoken.aspx

在此处详细了解Thread.Abort的问题:http://msdn.microsoft.com/en-us/library/ty8d3wta.aspx

编辑:我使用ManualResetEvent作为其线程安全,您可以使用它来同步线程中的处理,例如,如果您正在执行生产者/消费者模式。也可以使用volatile布尔值。我建议将线程保留在列表中,以防您需要等待它们完成,因此您可以加入每个线程。这可能适用于您的问题,也可能不适用。它通常是一个好主意,特别是如果你要离开,加入你所有的线程,让他们完成他们可能正在做的任何清理。

答案 1 :(得分:2)

你真的不应该使用Thread.Abort(),这可能非常危险。相反,您应该提供一些方法来向线程发出取消它们的信号。然后每个线程会定期检查它是否被取消,如果是,则结束。

执行此操作的一种方法是使用CancellationToken,这正是如此。支持取消的框架方法也适用于此类型。

您的代码可能如下所示:

// field to keep CancellationTokenSource:
CancellationTokenSource m_cts;

// in your method:

m_cts = new CancellationTokenSource();

foreach (DataGridViewRow dgvRow in dataGridView1.Rows)
{
    Class h = new Class(dgvRow.Cells["name"].Value.ToString());

    Thread trdmyClass = new Thread(() => h.SeeInfoAboutName(m_cts.Token));
    trdmyClass.IsBackground = true;
    trdmyClass.Start();
}

//somewhere else, where you want to cancel the threads:
m_cts.Cancel();

// the SeeInfoAboutName() method
public void SeeInfoAboutName(CancellationToken cancellationToken)
{
    while (!cancellationToken.IsCancellationRequested)
    {
        // do some work
    }
}

答案 2 :(得分:0)

将所有线程保留在List中,然后遍历列表并停止它们。