.net 在C#中使用两个线程打印偶数和奇数,即偶数线程和奇数线程

n7taea2i  于 2023-05-19  发布在  .NET
关注(0)|答案(6)|浏览(260)

/* 我的要求是一个线程应该打印偶数,另一个应该打印奇数。这些线程应按顺序打印数字(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++;
                }
            }
        }
    }
}
jq6vz3qz

jq6vz3qz1#

如果你想在两个线程之间交替,你可以使用两个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();
            }
        }
    }
}
kx7yvsdv

kx7yvsdv2#

您实际上可以使用Interlocked在线程之间进行通信。Interlocked允许您在两个线程之间并发共享一个变量。

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();
        }
    }
}
fae0ux8s

fae0ux8s3#

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);               
        }
    }
5kgi1eie

5kgi1eie4#

我们可以使用共享资源(在本例中为整数变量)和Task.Delay(1)来实现这一点,Task.Delay(1)允许循环暂停一段时间。

完整方案:

internal class Program
{
    int counter = 1;
    static void Main(string[] args)
    {
        var P = new Program();
        var t1 = P.OddThread();
        var t2 = P.EvenThread();
        //Wait for all task to complete
        Task.WaitAll(t1, t2);
        Console.ReadKey();
    }

    public async Task OddThread()
    {
        while (counter < 10)
        {
            // This delay will allow thread to switch and loop will be paused for some time.
            await Task.Delay(1);
            //counter is shared between threads, increment the value if it is odd number
            if (counter % 2 != 0)
            {
                Console.WriteLine(counter);
                counter++;
            }
        }
    }
    //Even Thread
    public async Task EvenThread()
    {
        while (counter < 10)
        {
            // This delay will allow thread to switch and loop will be paused for some time.
            await Task.Delay(1);
            //counter is shared between threads, increment the value if it is even number
            if (counter % 2 == 0)
            {
                Console.WriteLine(counter);
                counter++;
            }
        }
    }
lqfhib0f

lqfhib0f5#

试试这个方法。它使用任务库。

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);
    }
}
uz75evzq

uz75evzq6#

使用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();
            }
        }
    }
}

相关问题