プログラムを書こう!

実務や自作アプリ開発で習得した役に立つソフトウェア技術情報を発信するブログ

C#でSemaphoreSlimを使用する

この記事は2022年06月05日に投稿しました。

目次

  1. はじめに
  2. C#でSemaphoreSlimを使用する
  3. おわりに

1. はじめに

こんにちは、iOSのエディタアプリPWEditorの開発者の二俣です。
今回は業務で使用しているC#でSemaphoreSlimを使用する方法についてです。

目次へ

2. C#でSemaphoreSlimを使用する

C#でSemaphoreSlimを使用するには、以下のような実装にします。

実装例

※MicrosoftのAPI Referenceのサンプルを参考にしました。

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

namespace SampleSemaphoreSlim
{
    internal class Program
    {
        /// <summary>
        /// セマフォ
        /// </summary>
        private static SemaphoreSlim semaphore;

        /// <summary>
        /// ワーカースレッドのウェイト時間のパディング
        /// </summary>
        private static int padding;

        static void Main()
        {
            // 同時に許可されるセマフォ要求の初期値0、最大数3でセマフォを生成します。
            semaphore = new SemaphoreSlim(0, 3);
            Console.WriteLine($"{semaphore.CurrentCount}つのタスクがセマフォに入ることができます。");
            var tasks = new Task[5];

            // Create and start five numbered tasks.
            for (var i = 0; i <= 4; i++)
            {
                tasks[i] = Task.Run(() =>
                {
                    // Each task begins by requesting the semaphore.
                    Console.WriteLine($"タスク{Task.CurrentId}を開始し、セマフォ待ちします。");

                    int semaphoreCount;
                    semaphore.Wait();
                    try
                    {
                        Interlocked.Add(ref padding, 100);

                        Console.WriteLine($"タスク{Task.CurrentId}がセマフォに入りました。");

                        // ウェイトします。
                        Thread.Sleep(1000 + padding);
                    }
                    finally
                    {
                        semaphoreCount = semaphore.Release();
                    }
                    Console.WriteLine($"タスク{Task.CurrentId}をセマフォから解放します。前のセマフォカウント: {semaphoreCount}");
                });
            }

            // タスクを開始するため、ウェイトします。
            Thread.Sleep(500);

            Console.Write("セマフォを3つ解放します。");
            semaphore.Release(3);
            Console.WriteLine($"{semaphore.CurrentCount}つのタスクがセマフォに侵入可能です。");

            // 全てのタスクの完了を待ちます。
            Task.WaitAll(tasks);

            Console.WriteLine("メインスレッドを終了します。");

            Console.ReadKey();
        }
    }
}

実行結果

0つのタスクがセマフォに入ることができます。
タスク1を開始し、セマフォ待ちします。
タスク3を開始し、セマフォ待ちします。
タスク4を開始し、セマフォ待ちします。
タスク5を開始し、セマフォ待ちします。
タスク2を開始し、セマフォ待ちします。
セマフォを3つ解放します。3つのタスクがセマフォに侵入可能です。
タスク3がセマフォに入りました。
タスク1がセマフォに入りました。
タスク4がセマフォに入りました。
タスク1をセマフォから解放します。前のセマフォカウント: 0
タスク4をセマフォから解放します。前のセマフォカウント: 0
タスク5がセマフォに入りました。
タスク2がセマフォに入りました。
タスク3をセマフォから解放します。前のセマフォカウント: 0
タスク5をセマフォから解放します。前のセマフォカウント: 2
タスク2をセマフォから解放します。前のセマフォカウント: 1
メインスレッドを終了します。

API Reference

SemaphoreSlimクラス

目次へ

3. おわりに

前回

www.paveway.info

と同じようなクラスがあるようです。
Semaphoreクラスとの違いは、SemaphoreSlimクラスは、名前付きシステムセマフォをサポートせず、ローカルセマフォとしてのみ使用できるようです。

紹介している一部の記事のコードはGitlabで公開しています。
興味のある方は覗いてみてください。

目次へ


私が勤務しているニューラルでは、主に組み込み系ソフトの開発を行っております。
弊社製品のハイブリッドOS Bi-OSは高い技術力を評価されており、特に制御系や通信系を得意としています。
私自身はiOSモバイルアプリウィンドウズアプリを得意としております。
ソフトウェア開発に関して相談などございましたら、お気軽にご連絡ください。

また一緒に働きたい技術者の方も随時募集中です。
興味がありましたらご連絡ください。

EMAIL : info-nr@newral.co.jp / m-futamata@newral.co.jp
TEL : 042-523-3663
FAX : 042-540-1688

目次へ