使用两个线程即偶数线程和奇数线程在c#中打印偶数和奇数

时间:2015-11-23 08:11:32

标签: c# .net multithreading

/ *我的要求是 一个线程应该打印偶数,另一个应该打印奇数。 这些线程应按顺序打印数字(1,2,3,4,5 ...)

我已经完成了这段代码但是当我评论方法countThreadOdd.Start()或countThreadEven.Start()时,它不会只打印偶数或奇数。* /

class Program
{
    static Object locker = new Object();
    static LinkedList<int> number = new LinkedList<int>();
    static int counter = 0;
    static void Main(string[] args)
    {
        Thread countThreadOdd = new Thread(oddThread);
        Thread countThreadEven = new Thread(evenThread);

        //Thread Start
        countThreadOdd.Start();
        countThreadEven.Start();

        //main thread will untill below thread is in exection mode
        countThreadOdd.Join(10);
        countThreadEven.Join(10);

        Console.ReadLine();
    }

    //Odd Thread
    public static void oddThread()
    {
        for (; counter < 10; )
        {
            //Lock the another thread to enter in critial area
            lock (locker)
            {
                if (counter % 2 != 0)
                {
                    Console.WriteLine(counter);
                    counter++;
                }
            }
        }
    }

    //Even Thread
    public static void evenThread()
    {
        for (; counter < 10; )
        {
            //Lock the another thread to enter in critial area
            lock (locker)
            {
                if (counter % 2 == 0)
                {
                    Console.WriteLine(counter);  
                    counter++;
                }
            }
        }
    }
}

5 个答案:

答案 0 :(得分:1)

如果要在两个线程之间切换,可以使用两个AutoResetEvent对象来执行此操作,如下所示:

public static void oddThread()
{
    for (int i = 1; i < 10; i +=2)
    {
        evenReady.WaitOne();
        Console.WriteLine(i);
        oddReady.Set();
    }
}

public static void evenThread()
{
    for (int i = 0; i < 10; i += 2)
    {
        oddReady.WaitOne();
        Console.WriteLine(i);
        evenReady.Set();
    }
}

如果您只想运行其中一个主题,则可以使用ManualResetEvent来有效删除所有锁定。

一个完整的例子:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Dmr.Common.Resources;

namespace Demo
{
    class Program
    {
        static EventWaitHandle evenReady;
        static EventWaitHandle oddReady;

        static void Main(string[] args)
        {
            bool countOdd  = true; // Change these to true/false as wanted.
            bool countEven = true;

            if (countOdd && countEven)
            {
                evenReady = new AutoResetEvent(false);
                oddReady  = new AutoResetEvent(true); // Must be true for the starting thread.
            }
            else
            {
                evenReady = new ManualResetEvent(true);
                oddReady  = new ManualResetEvent(true);
            }

            Thread countThreadOdd = new Thread(oddThread);
            Thread countThreadEven = new Thread(evenThread);

            //Thread Start
            if (countOdd)
                countThreadOdd.Start();

            if (countEven)
                countThreadEven.Start();

            //main thread will untill below thread is in exection mode

            if (countOdd)
                countThreadOdd.Join();

            if (countEven)
                countThreadEven.Join();

            Console.WriteLine("Done");
            Console.ReadLine();
        }

        public static void oddThread()
        {
            for (int i = 1; i < 10; i +=2)
            {
                evenReady.WaitOne();
                Console.WriteLine(i);
                oddReady.Set();
            }
        }

        public static void evenThread()
        {
            for (int i = 0; i < 10; i += 2)
            {
                oddReady.WaitOne();
                Console.WriteLine(i);
                evenReady.Set();
            }
        }
    }
}

答案 1 :(得分:1)

    static AutoResetEvent evenReady = new AutoResetEvent(true);
    static AutoResetEvent oddReady = new AutoResetEvent(false);

    static void Main()
    {
        Thread countThreadOdd = new Thread(oddThread);
        Thread countThreadEven = new Thread(evenThread);
        countThreadOdd.Start();
        countThreadEven.Start();

        Console.WriteLine("Done");
        Console.ReadLine();

    }

    public static void oddThread()
    {
        for (int i = 1; i < 10; i += 2)
        {              
            oddReady.Set();
            evenReady.WaitOne();
            Console.WriteLine("Odd Thread: " + i);             
            //oddReady.Set();
        }
    }

    public static void evenThread()
    {
        for (int i = 0; i < 10; i += 2)
        {
            oddReady.WaitOne();
            evenReady.Set();
            Console.WriteLine("Even Thread: " + i);               
        }
    }

答案 2 :(得分:0)

尝试此方法。它使用任务库。

public class OddEvenThread
{
    public static async Task printEvenNumber(int n)
    {
        for (int i = 1; i <= n; i++) 
        {
            if (i % 2 == 0)
             Console.WriteLine(i);
        }

        await Task.Delay(0);
    }

    private static async Task printOddNumbers(int n)
    {
        for (int i = 1; i <= n; i++)
        {
            if (i % 2 == 1)
                Console.WriteLine(i);
        }

        await Task.Delay(0);
    }

    public async static Task printNumbers(int n)
    {

        Task evenNumbers = printEvenNumber(n);
        Task oddNumbers = printOddNumbers(n);

        List<Task> tasks = new List<Task>() { evenNumbers, oddNumbers };

       await Task.WhenAll(tasks);
    }
}

答案 3 :(得分:0)

使用AutoResetEvent,可以使线程彼此等待。在这里,两个线程写入从1到20的数字:

using System;
using System.Threading;

namespace oddeven
{
    class Program
    {
        static void Main(string[] args)
        {
            C c = new C();
            Thread t1 = new Thread(c.PrintOdd);
            Thread t2 = new Thread(c.PrintEven);

            t1.Start();
            t2.Start();
        }
    }

    class C
    { 
        AutoResetEvent e1 = new AutoResetEvent(true);
        AutoResetEvent e2 = new AutoResetEvent(true);
        int j = 1;
        public void PrintOdd()
        {
            while (j < 20)
            {
                if (j % 2 != 0)
                {
                    Console.WriteLine(j);
                    j++;
                }
                e1.Set();
                e2.WaitOne();
            }
        }

        public void PrintEven()
        {
            while (j <= 20)
            {
                e1.WaitOne();
                if (j % 2 == 0)
                {
                    Console.WriteLine(j);
                    j++;
                }
                e2.Set();
            }
        }
    }
}

答案 4 :(得分:-1)

您实际上可以使用互锁在线程之间进行通信。互锁可让您在两个线程之间同时共享一个变量。

using System;
using System.Threading;
using System.Threading.Tasks;

namespace InterlockedTest
{
    class Program
    {
        private static long _counter = 0;

        private static void printEvenTask()
        {
            while (Interlocked.Read(ref _counter) < 100)
            {
                if (Interlocked.Read(ref _counter) % 2 == 0)
                {
                    Console.WriteLine(Interlocked.Read(ref _counter));
                    Interlocked.Increment(ref _counter);
                }
            }
        }

        private static void printOddTask()
        {
            while (Interlocked.Read(ref _counter) < 100)
            {
                if (Interlocked.Read(ref _counter) % 2 == 1)
                {
                    Console.WriteLine(Interlocked.Read(ref _counter));
                    Interlocked.Increment(ref _counter);
                }
            }
        }

        static void Main(string[] args)
        {
            Task oddTask = Task.Run(() => printOddTask());
            Task evenTask = Task.Run(() => printEvenTask());

            oddTask.Wait();
            evenTask.Wait();

            Console.ReadKey();
        }
    }
}