http://stackoverflow.com/questions/20056727/need-to-understand-the-usage-of-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 }
}
Answer
i guess that if i run 50 thread at a time then code like SemaphoreSlim ss = new SemaphoreSlim(10); will force to run 10 active thread at time
That is correct; the use of the semaphore ensures that there won't be more than 10 workers doing this work at the same time.
Calling
WaitAsync
on the semaphore produces a task that will be completed when that thread has been given "access" to that token.await
-ing that task lets the program continue execution when it is "allowed" to do so. Having an asyncrhonous version, rather than callingWait
, is important both to ensure that the method stays asynchronous, rather than being synchronous, as well as deals with the fact that anasync
method can be executing code across several threads, due to the callbacks, and so the natural thread affinity with semaphores can be a problem.A side note:
DoPollingThenWorkAsync
shouldn't have theAsync
postfix because it's not actually asynchronous, it's synchronous. Just call itDoPollingThenWork
. It will reduce confusion for the readers.
Real Example
private const int MaxNumberOfThreads = 8; private static readonly SemaphoreSlim semaphore_ = new SemaphoreSlim(MaxNumberOfThreads, MaxNumberOfThreads);
public static void SearchTags([QueueTrigger("searchtags")] CrawlTagRequest request)
{ try { // wait for a slot to become available // then spawn a new thread semaphore_.Wait(); new Thread(() => ThreadProc(request)).Start(); } catch (Exception e) { Console.Error.WriteLine(e); } }
public static void ThreadProc(CrawlTagRequest request) { try { DownloadData(request); } catch (Exception e) { Console.Error.WriteLine(">> Error: {0}", e); } finally { // release a slot for another thread semaphore_.Release(); } }