1

問題: 複数のスレッドがリソースにアクセスしています。それらの数を定数に制限する必要がありMaxThreadsます。スレッド プールに入ることができないスレッドには、エラー メッセージが表示されます。

解決策: 以下のアルゴリズムで a の使用を開始しましたが、それには への呼び出しが必要であるBlockingCollection<string> poolことがわかりました。これは、常に着信スレッドを取得するため (デバッグ目的で以下の例では 10 にハードコードしました)、Web 要求を考えてください。 .BlockingCollectionCompleteAdding

public class MyTest {

    private const int MaxThreads = 3;

    private BlockingCollection<string> pool;

    public MyTest() { 
        pool = new BlockingCollection<string>(MaxThreads);
    }

    public void Go() {
        var addSuccess = this.pool.TryAdd(string.Format("thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
        if (!addSuccess) Console.WriteLine(string.Format("thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
        Console.WriteLine(string.Format("Adding thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
        Console.WriteLine(string.Format("Pool size: {0}", pool.Count));

        // simulate work
        Thread.Sleep(1000);

        Console.WriteLine("Thread ID#{0} " + Thread.CurrentThread.ManagedThreadId + " is done doing work.");
        string val;
        var takeSuccess = this.pool.TryTake(out val);
        if (!takeSuccess) Console.WriteLine(string.Format("Failed to take out thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
        Console.WriteLine("Taking out " + val);

        Console.WriteLine(string.Format("Pool size: {0}", pool.Count));
        Console.WriteLine(Environment.NewLine);
    }
}

static void Main()
{
    var t = new MyTest();

    Parallel.For(0, 10, x => t.Go());
}

これをよりよく達成する方法についてのアイデアはありますか?

ありがとう!

PS マルチスレッドの初心者です。資料を読むための提案があれば、大いに感謝します。

LE:得られた回答に基づいて、次のアルゴリズムを使用して目的の動作を実現できました。

public class MyTest {

    private const int MaxThreads = 3;

    private SemaphoreSlim semaphore;

    public MyTest() { 
        semaphore = new SemaphoreSlim(MaxThreads, MaxThreads);
    }

    public void Go() {

        Console.WriteLine(string.Format("In comes thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
        semaphore.Wait();

        try {

        Console.WriteLine(string.Format("Serving thread ID#{0}", Thread.CurrentThread.ManagedThreadId));
        // simulate work
        Thread.Sleep(1000);
        Console.WriteLine(string.Format("Out goes thread ID#{0}", Thread.CurrentThread.ManagedThreadId));

        }

        finally {
            semaphore.Release();
        }

    }
}

static void Main()
{
    var t = new MyTest();

    Parallel.For(0, 10, x=> t.Go());
}
4

1 に答える 1

5

一度に重要な領域にアクセスできる特定の数のスレッドを保護したい場合は、 SemaphoreまたはSemaphoreSlimを使用する必要があります。前者に比べて軽量な後者をお勧めします。

の欠点の 1 つSemaphoreSlimは、クロス プロセスでは機能しないことですが、それは問題ありませんSemaphore

フレームワークによってタイムアウト付きで提供される Wait メソッドのいずれかを使用して、セマフォがいっぱいかどうかをテストできます。

SemaphoreSlim semaphore = new SemaphoreSlim(3, 3);

if (!semaphore.Wait(0))
{
    //Already semaphore full.
    //Handle it as you like
}

http://www.albahari.com/threading/は、スレッドに関する非常に優れたリソースです。

于 2014-09-29T12:09:29.643 に答える