使用Sleep进行Thread Yield方法模拟

时间:2012-09-14 08:15:17

标签: c# .net multithreading

我试图了解.Net中的线程概念。 我无法使用Yield()方法。当我被10整除时,我希望控件转到并行线程。

请帮忙。

以下是我的示例代码:

class ThreadTest
{
    //Index i is declared as static so that both the threads have only one copy
    static int i;


    static void Main(string[] args)
    {
        Thread t = new Thread(WriteY);          
        i = 0;

        //Start thread Y    
        t.Start();                              
        //Do something on the main thread.
        for (; i < 100; i++)
        {
            if (i % 10 == 0)
            {
                //Simulate Yield() function
                Thread.Sleep(0);
                Console.WriteLine("The X thread");
            }
            Console.Write(i + ":X ");
        }
        Console.ReadKey(true);
    }

    static void WriteY()
    {
        for (; i < 100; i++)
        {
            if (i % 10 == 0)
            {
                //Simulate Yield() function
                Thread.Sleep(0);
                Console.WriteLine("The Y thread");
            }
            Console.Write(i + ":Y ");
        }
    }
}

我收到编译时错误:

  

System.Threading.Thread不包含'Yield'的定义

Tudor回答。此方法仅适用于.Net 4.0及更高版本。

理想情况下,我希望一个线程启动,并希望每个线程执行10个递增的i。使用我当前的方法,我得到所有'X'或全部'Y'。

修改 随着Tudor和TheHe的输入 - 我已经能够得到替代的X和Y.问题的关键是使用锁定对象。但是这段代码的输出是不可预测的。

3 个答案:

答案 0 :(得分:2)

Thread.Yield只会让调度程序选择一个可以运行的其他线程:

  

使调用线程产生执行到另一个线程   准备在当前处理器上运行。操作系统选择   要屈服的线程。

如果您的应用程序中的其他线程也在等待该锁定,您可以获得所需的一切,它们将无法运行。

顺便说一句,Yield是.NET 4.0+方法。确保您没有定位到早期版本。

修改:IMO,做你想做的事情应该使用事件:

class Test
{
    //Index i is declared as static so that both the threads have only one copy
    static int i;

    static AutoResetEvent parentEvent = new AutoResetEvent(true);
    static AutoResetEvent childEvent = new AutoResetEvent(false);

    static void Main(string[] args)
    {
        Thread t = new Thread(WriteY);

        i = 0;

        //Start thread Y
        t.Start();
        // Print X on the main thread
        parentEvent.WaitOne();
        while (i < 100)
        {                
            if (i % 10 == 0)
            {
                childEvent.Set();
                parentEvent.WaitOne();
            }
            Console.Write(i + ":Y ");
            i++;
        }
        t.Join();
    }

    static void WriteY()
    {
        childEvent.WaitOne();
        while (i < 100)
        {
            if (i % 10 == 0)
            {
                parentEvent.Set();
                childEvent.WaitOne();
            }
            Console.Write(i + ":X ");
            i++;
        }
    }
}

答案 1 :(得分:2)

忘记Thread.Yield;这与你想要做的事情无关。最终,您有一个lock,它使用Monitor来同步访问权限。在lock内,您的线程只能访问。你需要做的是暂时放弃锁;你这样做的方式是使用Monitor.Wait。但是,如果你Wait,你也会进入“等待”队列而不是“就绪”队列,所以为了确保每个线程得到关注,我们还需要Pulse,在Wait之前,也在最后(为了确保两个线程都有机会退出)。我们走了:

using System.Threading;
using System;
class ThreadTest
{
    //Index i is declared as static so that both the threads have only one copy
    static int i;

    //The lock object
    static readonly object locker = new object();

    static void Main(string[] args)
    {
        Thread t = new Thread(WriteY);

        i = 0;

        //Start thread Y
        t.Start();
        lock (locker)
        {
            // Print X on the main thread
            for (; i < 100; i++)
            {
                if (i % 10 == 0)
                {
                    Monitor.PulseAll(locker); // move any "waiting" threads to the "ready" queue
                    Monitor.Wait(locker); // relinquish the lock, and wait for a pulse
                    Console.WriteLine("The X thread");
                }
                Console.Write(i + ":X ");
            }
            Monitor.PulseAll(locker);
        }
        Console.ReadKey(true);
    }

    static void WriteY()
    {
        lock (locker)
        {
            for (; i < 100; i++)
            {
                if (i % 10 == 0)
                {
                    Monitor.PulseAll(locker); // move any "waiting" threads to the "ready" queue
                    Monitor.Wait(locker); // relinquish the lock, and wait for a pulse
                    Console.WriteLine("The Y thread");
                }
                Console.Write(i + ":Y ");
            }
            Monitor.PulseAll(locker); // move any "waiting" threads to the "ready" queue
        }
    }
}

答案 2 :(得分:1)

从我的角度来看,你在当前线程中锁定“locker”并希望将当前任务交给其他线程...... 锁是由第一个线程一直保持 - 它不能工作?!

如果要使用多个线程,则必须手动锁定对象...