同時に仕事をできる机(Task
)の数を決めるのが、**SemaphoreSlim
**です。
#基本
//机を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() を呼びます。
つづく・・・