【问题标题】:How to kill all threads immediately如何立即杀死所有线程
【发布时间】:2017-12-04 03:44:20
【问题描述】:

我制作了一个使用两个线程计算数字的小示例程序。它还会在计数旁边打印第二个数字,这样我就可以看到哪个线程打印了哪个数字。

现在我的目标是让两个线程在其中一个数为 7 后立即停止。我不知道该怎么做。我考虑过将线程数组作为参数传递给Counter,然后使用 foreach 循环中止两个线程。问题是t0 可能正在执行它并调用t0.Abort(),因此t1.Abort() 将不再被调用。

public static int count = 0;
private static object lockObject = new object();

static void Main(string[] args) {
    Thread t0 = new Thread(() => Counter(1, 10));
    Thread t1 = new Thread(() => Counter(10, 20));

    t0.Start();
    t1.Start();

    t0.Join();
    t1.Join();

    Console.ReadLine();
}

public static void Counter(int k, int m) {
    for(int i = k; i < m; i++) {
        lock (lockObject) {
            count++;
            Console.WriteLine(count + " " + i);
            if (i == 7) {
                /* 
                 * Code that will kill thread t0 and t1
                 */
            }
        }
    }
}

输出应该是这样的

1 1
2 2
3 10
4 11
5 12
6 13
7 14

有人建议如何杀死t0t1

【问题讨论】:

  • 您愿意使用Tasks 代替普通的线程吗?如果是这样,有一种简单的方法可以等到第一个在主线程中完成,然后您可以终止所有这些。
  • 您的目标是两个线程都不应该打印大于 14 的数字,对吧?而且计数永远不会减少,对吗?为什么不让每个线程在看到 count > 14 时杀死 自身(即返回)?
  • CancellationTokenSource 是你的朋友。
  • 不,我的目标是线程数到7时立即停止。第二个数字只是为了查看它来自哪个线程。

标签: c# multithreading


【解决方案1】:

使用标志,在本例中为“运行”。

public static int count = 0;
private static object lockObject = new object();
static bool run = true;

static void Main(string[] args) {
    Thread t0 = new Thread(() => Counter(1, 10));
    Thread t1 = new Thread(() => Counter(10, 20));        

    t0.Start();
    t1.Start();

    t0.Join();
    t1.Join();

    Console.ReadLine();
}

public static void Counter(int k, int m) {
    for(int i = k; i < m && run; i++) {
        lock (lockObject) {
            count++;
            Console.WriteLine(count + " " + i);
            if (i == 7) {
                run = false;
            }
        }
    }
}

【讨论】:

  • @Robbebeest 它非常很难正确使用,您需要非常了解它的工作原理以及确切如果您想要它的作用使用它。如果你不是,你应该使用正确的同步,比如lock,而不是尝试使用volatile
  • @Evk 完全正确:-)。如果你有机会读到这篇文章,这是一个很好的解释:stackoverflow.com/questions/72275/…
  • 这对我来说仍然是错误的。 run 可以是 true 进入循环并在另一个线程正在运行并拥有锁时被困在 lock 上。然后,其他线程会将run 设置为false,但为时已晚!另一个线程已经通过了该检查。为了纠正这个问题,标志检查应该在锁内。
【解决方案2】:

看看ManualResetEvent。您应该创建一个并在 Counter-method 的 for 循环中检查是否设置了事件,如果设置了,则中断 for 循环并返回。如果达到 7,只需设置事件。该事件是线程安全的。

对了,好像是大学作业;)下次自己试试吧。

public static int count = 0;
private static object lockObject = new object();
private ManualResetEvent finish = new ManualResetEvent(false);

static void Main(string[] args) {
    Thread t0 = new Thread(() => Counter(1, 10));
    Thread t1 = new Thread(() => Counter(10, 20));

    t0.Start();
    t1.Start();

    t0.Join();
    t1.Join();

    Console.ReadLine();
}

public static void Counter(int k, int m) {
    for(int i = k; i < m; i++) {

        lock (lockObject) {
            if (finish.waitOne(0))
                break;

            count++;
            Console.WriteLine(count + " " + i);
            if (i == 7)
                finish.set()
        }
    }
}

【讨论】:

  • 它仍然超过 7。我自己尝试了更多的东西,但有时你甚至不知道要搜索什么。例如,我从未听说过 ManualResetEvent。但是,是的,这只是一个大练习的一小部分;)
  • 啊,然后将 if (finish.isset()) 移动到 lockObject 之后。它仍然计数超过 7,因为一个线程正在等待 lockObject 并且不再查看事件(因为事件在锁定之前)。我更新了代码。
  • 您也可以使用信号量或 event.waitOne 方法来代替 lockObject。
【解决方案3】:

MSDN 不知道 ManualResetEvent.isset() 是什么,但 Matthias 的回答看起来是正确的。如果将isset() 替换为WaitOne(0),代码可以正常工作。

private static int count = 0;
private static ManualResetEvent finish = new ManualResetEvent(false);
private static int stopValue = 7;
private static int syncInterval = 0; //0ms
private static object lockObject = new object();
static void Main(string[] args)
{
    Thread t0 = new Thread(() => Counter(1, 10));
    Thread t1 = new Thread(() => Counter(10, 20));
    t0.Name = "Thread 1";
    t1.Name = "Thread 2";

    t0.Start();
    t1.Start();

    t0.Join();
    t1.Join();

    Console.ReadKey();
}
public static void Counter(int k, int m)
{
    for (int i = k; i < m; i++)
    {
        lock (lockObject)
        {
            if (finish.WaitOne(syncInterval))
                break;
            count++;
            Console.WriteLine($"{count} {i}");
            if (count == stopValue)
            {
                finish.Set();
            }
        }
    }
}

【讨论】:

  • 你是对的。我不再使用 C#,也没有安装 Visual Studio。所以代码是我脑子里想出来的
猜你喜欢
  • 2010-11-09
  • 2010-11-22
  • 1970-01-01
  • 2011-05-30
  • 2011-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多