LoginSignup
1
2

More than 3 years have passed since last update.

かんたんな「SemaphoreSlim」の使い方

Last updated at Posted at 2021-01-23

同時に仕事をできる机(Task)の数を決めるのが、SemaphoreSlimです。
company_syokuba_kengak:relaxed:u_business.png

基本

//机を2つ用意
SemaphoreSlim ss = new SemaphoreSlim(2);

//机が1つ埋まる
ss.Wait();

//机がさらに1つ埋まる
ss.Wait();

//2つとも埋まった机のうち、1つだけ空ける
ss.Release(1);

//空いてる机の数を確認
Console.WriteLine(ss.CurrentCount);
//実行結果は、1

Waitで机を使う。
Releaseで机を空けるか、新しい机を用意する。
CurrentCountで机の数を確認

かんたんな例

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

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

        SemaphoreSlim ss = new SemaphoreSlim(0);    //最初は、机を1つも作らない
        ss.Release(1);      //机を1つだけ追加

        //机が1つしかないので、作業1だけが実行される
        Task task1 = Task.Run(() =>{ss.Wait();  Console.WriteLine("作業1");});
        Task task2 = Task.Run(() =>{ss.Wait();  Console.WriteLine("作業2");});

        //1つしかない机は、作業1で埋まっているので、0
        Console.WriteLine(  ss.CurrentCount);

        Console.ReadLine();
    }
}

Taskを実行しようとしても、空いてる机の数しか実行されない

引数

SemaphoreSlim ss = new SemaphoreSlim(1, 6); 

第1引数は、机の数(あとから追加できる)
第2引数は、机の最大数
机は1つしかないが、最大6つまで増やせられる。

SemaphoreSlim ss = new SemaphoreSlim(1); 

引数は机の数(最大数は未設定なので、あとからいくらでも追加できる)

Waitと、WaitAsyncの違い

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

class Program {
    static void Main(string[] args) {
        Sub();
        Console.WriteLine("main");      //A
        Console.ReadLine();
    }
    public static async Task Sub() {
        SemaphoreSlim ss = new SemaphoreSlim(2);
        List<Task> list = new List<Task>();
        int num = 10;

        while(num-- > 0) {
            await ss.WaitAsync();       //B     Aが先に実行される(非同期)
            //ss.Wait();                //C     Aが後に実行される(同期)

            list.Add(   Task.Run(   () => {
                Thread.Sleep(100);
                Console.WriteLine("-");
                ss.Release();
            }));
        }
        await Task.WhenAll(list);
    }
}

Waitは、呼び出し元を待機させ(同期)
WaitAsyncは、待機させません(非同期)

Waitメソッドは入れたらTrueを返します。
既に満席で入れなかったらFalseを返します。

キャンセル

CancellationToken はまず CancellationTokenSource を生成した上で、
CancellationTokenSource.Token より取得します。

キャンセルを要求するには CancellationTokenSource.Cancel() を呼びます。

つづく・・・

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2