[c#] SemaphoreSlim의 사용법을 이해해야합니다.

여기에 제가 가지고있는 코드가 있지만 무엇을하는지 이해가되지 않습니다 SemaphoreSlim.

async Task WorkerMainAsync()
{
    SemaphoreSlim ss = new SemaphoreSlim(10);
    List<Task> trackedTasks = new List<Task>();
    while (DoMore())
    {
        await ss.WaitAsync();
        trackedTasks.Add(Task.Run(() =>
        {
            DoPollingThenWorkAsync();
            ss.Release();
        }));
    }
    await Task.WhenAll(trackedTasks);
}

void DoPollingThenWorkAsync()
{
    var msg = Poll();
    if (msg != null)
    {
        Thread.Sleep(2000); // process the long running CPU-bound job
    }
}

무엇 await를 수행 ss.WaitAsync();하고 ss.Release();있습니까?

한 번에 50 개의 스레드를 실행하고 다음과 같은 코드를 작성하면 한 번에 SemaphoreSlim ss = new SemaphoreSlim(10);10 개의 활성 스레드를 실행해야합니다.

10 개의 스레드 중 하나가 완료되면 다른 스레드가 시작됩니다. 내가 옳지 않다면 샘플 상황을 이해하도록 도와주세요.

await함께 필요 ss.WaitAsync();합니까? 무엇을 ss.WaitAsync();합니까?



답변

한 번에 50 개의 스레드를 실행하면 SemaphoreSlim ss = new SemaphoreSlim (10); 한 번에 10 개의 활성 스레드를 실행하도록 강제합니다.

맞아요; 세마포어를 사용하면 동시에이 작업을 수행하는 작업자가 10 명 이상이되지 않습니다.

WaitAsync세마포어를 호출 하면 해당 스레드에 해당 토큰에 대한 “액세스”가 주어 졌을 때 완료 될 작업이 생성됩니다. await-이 작업을 통해 “허용 된”경우 프로그램이 계속 실행되도록합니다. 를 호출하는 것보다 비동기 버전 Wait을 사용하는 것은 메서드가 동기가 아닌 비동기 상태를 유지하도록 보장하고 메서드가 async콜백으로 인해 여러 스레드에서 코드를 실행할 수 있다는 사실을 처리하는 데 중요합니다. 세마포어와의 자연스러운 스레드 친 화성이 문제가 될 수 있습니다.

참고 : 실제로 비동기 적이 지 않고 동기식이기 때문에 접미사 DoPollingThenWorkAsync가 없어야 Async합니다. 그냥 전화하십시오 DoPollingThenWork. 독자들에게 혼란을 줄 것입니다.


답변

모퉁이에있는 유치원에서는 SemaphoreSlim을 사용하여 체육실에서 얼마나 많은 아이들이 놀 수 있는지 제어합니다.

그들은 방 밖에있는 바닥에 5 쌍의 발자국을 그렸습니다.

아이들이 도착하면, 그들은 신발을 무료 발자국에두고 방으로 들어갑니다.

게임을 마치면 나와서 신발을 모아서 다른 아이를 위해 슬롯을 “공개”합니다.

아이가 도착하고 남은 발자국이 없으면 다른 곳에서 놀거나 잠시 머물면서 가끔씩 확인합니다 (예 : FIFO 우선 순위 없음).

교사가 주위에있을 때 그녀는 복도 반대편에 5 개의 발자국이있는 추가 행을 “방출”하여 5 명의 어린이가 동시에 교실에서 놀 수 있도록합니다.

또한 SemaphoreSlim과 동일한 “함정”이 있습니다.

아이가 게임을 마치고 신발을 꺼내지 않고 방을 나가면 ( “릴리스”를 트리거하지 않음) 이론적으로는 빈 슬롯이 있더라도 슬롯이 차단 된 상태로 유지됩니다. 하지만 아이는 보통 말을 듣습니다.

때로는 한 두 명의 교활한 아이가 다른 곳에 신발을 숨기고 방에 들어갑니다. 모든 발자국이 이미 찍혔더라도 (즉, SemaphoreSlim은 방에있는 아이 수를 “정말”제어하지 않습니다).

방의 과밀로 인해 아이들이 울고 교사가 방을 완전히 닫는 경향이 있기 때문에 이것은 일반적으로 잘 끝나지 않습니다.


답변

이 질문은 실제로 카운트 다운 잠금 시나리오와 관련이 있지만 SemaphoreSlim을 간단한 비동기 잠금으로 사용하려는 사람들을 위해 찾은이 링크를 공유 할 가치가 있다고 생각했습니다. 코딩을 더 깔끔하고 안전하게 만들 수있는 using 문을 사용할 수 있습니다.

http://www.tomdupont.net/2016/03/how-to-release-semaphore-with-using.html

나는 스왑했다 _isDisposed=true_semaphore.Release()케이스에 든 여러 번 호출있어 비록 그 폐기에 주위를.

또한 SemaphoreSlim은 재진입 잠금이 아닙니다. 즉, 동일한 스레드가 WaitAsync를 여러 번 호출하면 세마포어의 개수가 매번 감소된다는 점에 유의해야합니다. 간단히 말해 SemaphoreSlim은 스레드를 인식하지 않습니다.

코드 품질에 대한 질문과 관련하여 릴리스가 항상 릴리스되도록하기 위해 최종적으로 트라이 파이널 내에 릴리스를 배치하는 것이 좋습니다.


답변