我的队列很有趣,任何想法为什么?

时间:2010-10-17 03:17:13

标签: c# queue

我想用队列进行一些测试,并使用Queue.Synchronized查看当有两个线程将东西放入队列时,以及第三个线程读取它时它是如何工作的。它似乎相当简单,但它不能正常工作,我不知道为什么。对我来说可能是一个愚蠢的错误。不过还有一点。

class Program
{
    public int this1 = 0;
    static void Main(string[] args)
    {
        Tester test1 = new Tester();

        Queue myQ = new Queue();
        Tester.myQ = Queue.Synchronized(myQ);
        Thread test1_thread = new Thread(new ThreadStart(test1.test1));
        Thread test1_thread2 = new Thread(new ThreadStart(test1.test1));

        test1_thread.Start();
        test1_thread2.Start();

        int i = 0;
        while (i <= 10)
        {

            i++;
        go_back_here:
            try
            {
                Tester.myQ.Enqueue(40);
                Console.WriteLine("did it");
                int holding = Convert.ToInt32(Tester.myQ.Dequeue());
                Console.WriteLine("reading out {0}: {1}", i);
            }
            catch
            {
                //Console.Write("e");
                //goto go_back_here;
            }
        }
        Console.ReadLine();
    }


}

class Tester
{

    public static Queue myQ;
    public void test1()
    {
        int this1 = 0;

        while (this1 <= 10)
        {
            Console.WriteLine("Doing something {0}", this1);
            myQ.Enqueue(this1);
            Console.WriteLine("(peek) {0}", myQ.Dequeue());
            this1++;
        }

    }
}

通过我自己的测试,我发现两个Tester线程正在将内容加载到队列中。当我的主循环尝试将其取消时,我会收到错误,说队列是空的。我把偷看然后Dequeues放在测试线程中,他们能够很好地显示线程中的东西。

然后我想知道我是否以某种方式从主循环访问错误的队列(OOP不是我的强项,仍在学习它),所以我添加了“Tester.myQ.Enqueue(40);”看看我是否可以粘上一些东西。我的peeks / Dequeues没有显示它,但是,当我添加“did it”写行时它会显示出来。我已经运行了很多次这个程序,主循环中的40只出现在测试线程中打印出Dequeue时“就好了”。从来没有评论过它。

对于这个主题有更多了解的人是否会对正在发生的事情有所了解? (是的,我知道我使用goto是一件很糟糕的事情,我让它滑动,因为这应该是一个简单的测试)

1 个答案:

答案 0 :(得分:2)

似乎你最初的问题是你的主线程太快地访问了队列(因为线程开始在同一时间放入其中的东西)。在从主线程中的队列中读取之前,您需要确保线程已完成工作。您可以在检查线程设置的某个全局变量的条件时,通过调用Thread.Join或者Thread.Sleep循环来等待它们。没有睡眠或加入的while循环是不够的。

此外,你的“偷看”并不是真正的偷看,因为它实际上删除了该项目。您需要使用Console.WriteLine("(peek) {0}", myQ.Peek());而不是myQ.Dequeue()