-2


2 つのスレッドを使用して 10 までカウントするプログラムを作成する必要があります。
1 つのスレッドは偶数を出力し、もう 1 つのスレッドは奇数を出力する必要があります。
これらのスレッドは、番号を順番に出力する必要があります (1、2、3、4、5...)。

私はこのコードを実行しましたが、うまくいかないようです...何かアイデアはありますか?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        private static AutoResetEvent autoEvent;
        private static int num = 10;

        static void DoWork(object data)
        {
            var counter = (int)data;

            if (counter == 1)
            {
                autoEvent.WaitOne();
            }

            while (counter <= num)
            {
                Console.WriteLine(counter);
                counter += 2;
                autoEvent.Set();
                autoEvent.WaitOne();
            }
        }

        static void Main(string[] args)
        {
            autoEvent = new AutoResetEvent(false);

            var evenCounter = new Thread(DoWork);
            evenCounter.Start(0);

            var notEvenCounter = new Thread(DoWork);
            notEvenCounter.Start(1);

            Console.ReadLine();
        }
    }
}
4

3 に答える 3

1

ここにあなたの問題があるようです:

   autoEvent.Set();
   autoEvent.WaitOne();

ロックを解放し、すぐにロックを待機します。これにより、任意の実行パターンが発生します。

2 つのロックを使用して、1 つのスレッドがもう 1 つのスレッドをブロックできるようにすることをお勧めします。

于 2014-05-25T16:55:22.487 に答える
1

そのコードでは、すでにシグナル状態にあるautoEvent.WaitOne()ため、ブロックされない場合があります。AutoResetEvent

        autoEvent.Set();
        autoEvent.WaitOne();

そのスレッドは、計画どおりに別のスレッドを待機しません。
この問題を解決するには、2 秒を使用する必要がありますAutoResetEvent。1 つのスレッドが最初のAutoResetEventスレッドを待機し、2 番目のスレッドが 2 番目のスレッドを待機しAutoResetEventます。各スレッドはAutoResetEvent、別のスレッドに「属する」ことを通知します。
私のアイデアを実証するために、変更が必要な場所だけのコード行を示します。

private static AutoResetEvent autoEvents[] = new AutoResetEvent[2];

...

autoEvents[0] = new AutoResetEvent(false);
autoEvents[1] = new AutoResetEvent(false);

...

var counter = (int)data;
int initial_counter = counter;

...

if (counter == 1)
{
autoEvents[initial_counter].WaitOne();
}

...

autoEvents[1 - initial_counter].Set();
autoEvents[initial_counter].WaitOne();

DoWork の最後にAutoResetEvent、別のスレッドの無限のブロックを回避するために適切なシグナルを送信します。

autoEvents[1 - initial_counter].Set();
于 2014-05-25T17:59:40.133 に答える
0
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ThreadTest
{
    class Program
    {
        static void Main(string[] args)
        {

            Thread t1 = new Thread(Method1);
            Thread t2 = new Thread(Method2);
            t1.Start();
            Thread.Sleep(100);
            t2.Start();
            t1.Join();
            t2.Join();
            _autoEvent1.Close();
            _autoEvent2.Close();
        }

        private static void Method1()
        {

            do
            {
               _autoEvent2.WaitOne();

                if (!SharedCode(Thread.CurrentThread.ManagedThreadId))
                {
                    break;
                }

                _autoEvent1.Set();
            } while (true);
        }

        private static void Method2()
        {
            do
            {
                _autoEvent1.WaitOne();
                //_autoEvent2.Set();
                if (!SharedCode(Thread.CurrentThread.ManagedThreadId))
                    break;
                _autoEvent2.Set();
            } while (true);
        }

        private static bool SharedCode(int threadId)
        {
           lock (_lockObject)
            {

                Interlocked.Increment(ref _count);
                if (_count > 10)
                    return false;
                Console.WriteLine("ThreadId={0} , count={1}", threadId,_count);
            }

            return true;
        }
        private  static AutoResetEvent _autoEvent1 = new AutoResetEvent(true);
        private static AutoResetEvent _autoEvent2 = new AutoResetEvent(true);
        private static Object _lockObject = new object();
        private static int _count = 0;
    }
}
于 2016-12-02T13:41:04.663 に答える