【问题标题】:CountDownEvent won't wait until all the signals have been calledCountDownEvent 不会等到所有信号都被调用
【发布时间】:2013-05-14 04:22:40
【问题描述】:

我正在查看此站点以获取 threads。 我一直在使用代码来回答“CountdownEvent 是否停止所有线程?”这个问题。 我得到的答案是否定的。然后我决定使用传递给 CountdownEvent 的数字。这是我的代码

namespace ThreadPractice
{
    class Program
    {
        static CountdownEvent CountDown = new CountdownEvent(4);
        static void Main()
        {
            new Thread(() => SaySomething("I am Thread one.")).Start();
            new Thread(() => SaySomething("I am thread two.")).Start();
            new Thread(() => SaySomethingElse("Hello From a different Thread")).Start();
            new Thread(() => SaySomething("I am Thread Three.")).Start();
            CountDown.Wait();
            Console.Read();
        }

        static void SaySomething(string Something)
        {
            Thread.Sleep(1000);
            Console.WriteLine(Something);
            CountDown.Signal();
        }

        static void SaySomethingElse(string SomethingElse)
        {
            Thread.Sleep(1000);
            Console.WriteLine(SomethingElse);
        }
    }
}

我预计调用 SaySomethingELse() 的线程会执行,但其他线程也会执行,即使只调用了四个信号。

为什么要这样做?

谢谢,

dhoehna

【问题讨论】:

  • 您为什么希望其他线程执行?只有您的主线程使用Wait。其他人只是发出信号倒计时。
  • 我希望所有线程都能运行并打印一些东西,然后让您的程序在 CountDown.Wait() 调用上永远阻塞。倒计时的重点是阻塞一个线程,直到一堆其他线程发出信号表明可以继续安全。
  • @dlev 问题是我忘记在所有线程上调用等待。我认为等待是一个笼统的陈述。

标签: c# multithreading countdownevent


【解决方案1】:

在我看来,您的 SignalWait 方向错误。如果您希望SaySomething 呼叫等待倒计时到达 0,您应该呼叫 Wait。这是一个例子:

using System;
using System.Threading;

namespace ThreadPractice
{
    class Program
    {
        static CountdownEvent CountDown = new CountdownEvent(4);
        static void Main()
        {
            new Thread(() => SaySomething("I am Thread one.")).Start();
            new Thread(() => SaySomething("I am thread two.")).Start();
            new Thread(() => SaySomethingElse("Hello From a different Thread")).Start();
            new Thread(() => SaySomething("I am Thread Three.")).Start();
            for (int i = 0; i < 4; i++)
            {
                Console.WriteLine("Calling Signal (time #{0})", i);
                CountDown.Signal();
                Thread.Sleep(1000);
            }
            Console.WriteLine("Done"); 
        }

        static void SaySomething(string Something)
        {
            CountDown.Wait();
            Console.WriteLine(Something);
        }

        static void SaySomethingElse(string SomethingElse)
        {
            Thread.Sleep(1000);
            Console.WriteLine(SomethingElse);
        }
    }
}

输出:

Calling Signal (time #0)
Hello From a different Thread
Calling Signal (time #1)
Calling Signal (time #2)
Calling Signal (time #3)
I am Thread one.
I am Thread Three.
I am thread two.
Done

【讨论】:

  • 我明白了。您的 for 循环在每个线程上调用 wait 。因此,为了相对于倒数计时器阻塞线程,我需要在每个线程上调用 wait 。非常感谢。
【解决方案2】:

嗯...在我看来,您想等待所有线程完成,然后再继续主线程。如果是这样,您忘记了 SaySomethingElse() 中的 Signal()。这可以防止 CountDown.CurrentCount 达到 0(零),这就是您的主线程“卡住”的原因。您将其设置为 4,它只会下降到 1(一)。修复它,你应该得到想要的?结果:

class Program
{
    static CountdownEvent CountDown = new CountdownEvent(4);
    static void Main()
    {
        new Thread(() => SaySomething("I am Thread one.")).Start();
        new Thread(() => SaySomething("I am thread two.")).Start();
        new Thread(() => SaySomethingElse("Hello From a different Thread")).Start();
        new Thread(() => SaySomething("I am Thread Three.")).Start();

        CountDown.Wait();

        Console.WriteLine("Done!");
        Console.Read();
    }

    static void SaySomething(string Something)
    {
        Thread.Sleep(1000);
        Console.WriteLine(Something);
        CountDown.Signal();
    }

    static void SaySomethingElse(string SomethingElse)
    {
        Thread.Sleep(1000);
        Console.WriteLine(SomethingElse);
        CountDown.Signal();
    }
}

输出:

I am Thread one.
I am thread two.
Hello From a different Thread
I am Thread Three.
Done!

【讨论】:

  • 谢谢,但这与我所寻找的相反。这不是我希望线程等待。就是我将 Countdown 设置为四个,我只使用了三个信号并且线程仍在执行。我想知道为什么会这样。我想阻止线程执行,因为我将倒数计时器设置为 4 并且只进行了三个信号调用。
  • 实际调用 Wait() 的线程是停止的线程。在您的原始代码中,这是主线程。它做了它应该做的,因为计数器没有达到零而停止。其他线程只是自己执行的普通线程。调用 Signal() 不会影响它们的运行方式,它只会减少计数。 Jon 的示例翻转了它并让每个单独的线程等待直到计数为零,而不是主线程等待。主线程发出足够多的信号以允许其他线程继续。很高兴你把这一切都解决了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-06
  • 2016-02-09
  • 2021-10-24
  • 1970-01-01
相关资源
最近更新 更多