2

私はサンプルアプリケーションを持っていますが、誰かがこれに光を当てることができるかどうか疑問に思います。デバッガーのコードへのステップへのステップをforループにブレークポイントを設定すると、なぜあるスレッドから別のスレッドに切り替わるのですか?実行時にアプリケーションを実行するときにこれを行います...以下のコードを参照してください。

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

namespace TPLSample
{
    class Program
    {

        static void Main(string[] args)
        {
           Management m = new Management();

           Task a = new Task(() => m.Operation1());
           a.Start();
           Task b = new Task(() => m.Operation2());
           b.Start();


            Console.ReadLine();
        }
    }
    public class Management
    {
        A a = null;
        B b = null;

        public void Operation1()
        {
            a = new A();

        }
        public void Operation2()
        {
            b = new B();
        }
    }
    public class A
    {  Client a = new Client();
        public A()
        {
            while (true)
            {
                a.Test("Im AAAAA");
            }
        }
    }
    public class B
    {
        Client a = new Client();
        public B()
        {
            while (true)
            {
                a.Test("Im BBBBB");
            }
        }
    }
    public class Client
    {
        Object ibj = new Object();


        public void Test(string item)
        {
            lock (ibj)
            {
                for (int i = 0; i < 200000; i++)
                {
                    Console.WriteLine(item);
                }
            }

        }
    }
}

この結果は、AsとBの混合物です。ロックは、結果が順番に終わるようにスレッドをブロックすることを想定していませんか?WHILEループが永久に実行されることを除いて、私が書いているアプリケーションでも同じことが起こっています(各タスクは継続的にポーリングする必要があります)。WHILEループが永久に実行される場合、一方のWHILEループが他方の実行を妨げることを望まないため、2つのタスクを開始していることに注意してください。CLIENTクラスのその関数に順番に移動させるにはどうすればよいですか?

4

2 に答える 2

7

これは、オブジェクト作成ツリーを注意深くトレースすると、各スレッドが異なるロックオブジェクトを使用していることに気付くため、lockステートメントが役に立たなくなるために発生します。

オブジェクトの作成は次のように行われます。

                 new A() -> new Client() -> new Object()
                / 
new Management()
                \
                 new B() -> new Client() -> new Object()

右側の最後の2つのオブジェクトをロックとして使用しており、それらが異なるオブジェクトであることがはっきりとわかります。

ロックを静的にしてみてください。

public class Client
{
    static Object ibj = new Object();
    ...

または、階層を再考して、両方のタスクに同じロックを渡します。

于 2012-05-16T17:36:17.430 に答える
2

ロックを機能させるには、各オブジェクトが同じオブジェクトにアクセスできる必要があります。これを行うには、ibjオブジェクトを静的にするか、Clientクラスに渡します。

public class Client
{
    static Object ibj = new Object();


    public void Test(string item)
    {
        lock (ibj)
        {
            for (int i = 0; i < 200000; i++)
            {
                Console.WriteLine(item);
            }
        }

    }
}
于 2012-05-16T17:38:53.643 に答える