난 당신과 같이 구성하면 SemaphoreSlim은 한 번에 하나의 스레드에 의해 실행되는 코드의 일부를 제한 할 것을 나타냅니다 SemaphoreSlim SemaphoreSlim MSDN 에 대한 문서 읽고 그러나SemaphoreSlim (.NET)이 동일한 스레드가 블록을 입력하지 못하도록합니까?
SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(1, 1);
을, 그것은 '아무튼 t는 해당 코드에 스레드가 액세스하는 것을 중지하는지 나타냅니다. 이것은 비동기와 함께오고 기다리고 있습니다. 메서드에서 await을 사용하면 컨트롤에서 해당 메서드를 끝내고 완료된 작업이나 스레드가 반환됩니다. 예제에서는 비동기 버튼 핸들러가있는 버튼을 사용합니다. 'await'와 함께 다른 메소드 (Function1)를 호출합니다. 차례로 기능 1 내가 SemaphoreSlim이() 내 Task.Run 주변
await Task.Run(() => Function2(beginCounter));
를 호출합니다. 그것은 확실히 그것이 Function2에 점점에서 동일한 스레드를 중지 것처럼 보인다. 그러나 이것은 문서에서 (내가 읽었을 때) 보장 할 수는 없지만 그 값을 계산할 수 있는지 궁금합니다.
아래에 완전한 예를 게시했습니다.
감사합니다,
데이브
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace AsynchAwaitExample
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private readonly SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(1, 1);
public MainWindow()
{
InitializeComponent();
}
static int beginCounter = 0;
static int endCounter = 0;
/// <summary>
/// Suggest hitting button 3 times in rapid succession
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void button_Click(object sender, RoutedEventArgs e)
{
beginCounter++;
endCounter++;
// Notice that if you click fast, you'll get all the beginCounters first, then the endCounters
Console.WriteLine("beginCounter: " + beginCounter + " threadId: " + Thread.CurrentThread.ManagedThreadId);
await Function1(beginCounter);
Console.WriteLine("endCounter: " + endCounter + " threadId: " + Thread.CurrentThread.ManagedThreadId);
}
private async Task Function1(int beginCounter)
{
try
{
Console.WriteLine("about to grab lock" + " threadId: " + Thread.CurrentThread.ManagedThreadId + " beginCounter: " + beginCounter);
await _semaphoreSlim.WaitAsync(); // get rid of _semaphoreSlim calls and you'll get into beginning of Function2 3 times before exiting
Console.WriteLine("grabbed lock" + " threadId: " + Thread.CurrentThread.ManagedThreadId + " beginCounter: " + beginCounter);
await Task.Run(() => Function2(beginCounter));
}
finally
{
Console.WriteLine("about to release lock" + " threadId: " + Thread.CurrentThread.ManagedThreadId + " beginCounter: " + beginCounter);
_semaphoreSlim.Release();
Console.WriteLine("released lock" + " threadId: " + Thread.CurrentThread.ManagedThreadId + " beginCounter: " + beginCounter);
}
}
private void Function2(int beginCounter)
{
Console.WriteLine("Function2 start" + " threadId: " + Thread.CurrentThread.ManagedThreadId + " beginCounter: " + beginCounter);
Thread.Sleep(1000);
Console.WriteLine("Function2 end" + " threadId: " + Thread.CurrentThread.ManagedThreadId + " beginCounter: " + beginCounter);
return;
}
}
}
샘플 출력은 당신이 버튼을 3 번을 클릭합니다. Function2는 주어진 카운터가 다시 시작되기 전에 항상 종료됩니다. 당신이 SemaphoreSlim 제거하면
beginCounter: 1 threadId: 9
about to grab lock threadId: 9 beginCounter: 1
grabbed lock threadId: 9 beginCounter: 1
Function2 start threadId: 13 beginCounter: 1
beginCounter: 2 threadId: 9
about to grab lock threadId: 9 beginCounter: 2
beginCounter: 3 threadId: 9
about to grab lock threadId: 9 beginCounter: 3
Function2 end threadId: 13 beginCounter: 1
about to release lock threadId: 9 beginCounter: 1
released lock threadId: 9 beginCounter: 1
grabbed lock threadId: 9 beginCounter: 2
Function2 start threadId: 13 beginCounter: 2
endCounter: 3 threadId: 9
Function2 end threadId: 13 beginCounter: 2
about to release lock threadId: 9 beginCounter: 2
released lock threadId: 9 beginCounter: 2
endCounter: 3 threadId: 9
grabbed lock threadId: 9 beginCounter: 3
Function2 start threadId: 13 beginCounter: 3
Function2 end threadId: 13 beginCounter: 3
about to release lock threadId: 9 beginCounter: 3
released lock threadId: 9 beginCounter: 3
endCounter: 3 threadId: 9
는 당신이 얻을 것이다 호출
beginCounter: 1 threadId: 10
about to grab lock threadId: 10 beginCounter: 1
grabbed lock threadId: 10 beginCounter: 1
Function2 start threadId: 13 beginCounter: 1
beginCounter: 2 threadId: 10
about to grab lock threadId: 10 beginCounter: 2
grabbed lock threadId: 10 beginCounter: 2
Function2 start threadId: 14 beginCounter: 2
beginCounter: 3 threadId: 10
about to grab lock threadId: 10 beginCounter: 3
grabbed lock threadId: 10 beginCounter: 3
Function2 start threadId: 15 beginCounter: 3
Function2 end threadId: 13 beginCounter: 1
about to release lock threadId: 10 beginCounter: 1
released lock threadId: 10 beginCounter: 1
endCounter: 3 threadId: 10
Function2 end threadId: 14 beginCounter: 2
about to release lock threadId: 10 beginCounter: 2
released lock threadId: 10 beginCounter: 2
endCounter: 3 threadId: 10
답변과 참조에 감사드립니다. – Dave