0

I'm using a semaphore to spread work onto a fixed amount of threads and after all of the work is done i want to proceed all of the results. I'm currently waiting until the CurrentCount of the semaphore is back to the original limit however I'm curious if there is a better approach to wait until no more work is left/all threads are back available?

var semaphore = new SemaphoreSlim(5, 5);
foreach (var site in foundSites)
{
   await semaphore.WaitAsync();
   _ = Task.Run(async () =>
   {
      <PROCESSING CODE>
   }).ContinueWith(task => semaphore.Release());
}

while (semaphore.CurrentCount < 5)
{
   await Task.Delay(1);
}

<PROCESSING OF ALL PROCESSED ITEMS>
  • Please show some code so we can help – Mouse On Mars Oct 20 '20 at 20:04
  • In C language under Linux/GLIBC, you can for example use a POSIX barrier : cf. pthread_barrier_init(), pthread_barrier_wait(). You must have the same principle available with C#. – Rachid K. Oct 20 '20 at 20:06
  • The `CurrentCount` property is intended for informational purposes (logging). Using it for control-flow introduces almost always race conditions. Btw have you considered using any of the built-in APIs that facilitate parallelism (`Parallel` class, PLINQ, TPL Dataflow), instead of writing a custom one from scratch? – Theodor Zoulias Oct 20 '20 at 20:53
  • I edited my original post and put in the code that I'm currently using for this. I attempted to implement a barrier already however it didn't seem to fit my needs and didn't really change anything. – kapitallebensve Oct 20 '20 at 21:05
  • Since you want to know when all of the work is done, *don't throw away all of the tasks that specifically are designed to tell you when that piece of work is done*. – Servy Oct 20 '20 at 21:06
  • Since your workload is asynchronous, this question should have more relevant answers: [How to limit the amount of concurrent async I/O operations?](https://stackoverflow.com/questions/10806951/how-to-limit-the-amount-of-concurrent-async-i-o-operations). – Theodor Zoulias Oct 20 '20 at 21:13
  • I'll take a look at the linked existing questions, thanks. – kapitallebensve Oct 20 '20 at 21:24
  • kapitallebensve I posted an answer in the linked question, that may be quite close to what you were trying to achieve ([here](https://stackoverflow.com/questions/10806951/how-to-limit-the-amount-of-concurrent-async-i-o-operations/64455549#64455549)). – Theodor Zoulias Oct 21 '20 at 01:59
  • @Servy I discovered that keeping the tasks around is not required, and throwing them away can be OK (and possibly advantageous). I posted a relevant answer [here](https://stackoverflow.com/questions/10806951/how-to-limit-the-amount-of-concurrent-async-i-o-operations/64455549#64455549). – Theodor Zoulias Oct 21 '20 at 02:00
  • Sure you *could* add a continuation to the task that takes all of the useful information out of it and puts it into a different data structure like you did, or you could just use the TPL to do it and keep track of the task. But either way, that's still using the task and not just throwing it away as the OP is doing. – Servy Oct 21 '20 at 03:38
  • @Servy the OP may not be interested about the result of the tasks, nor their exceptions, in which case the continuation just needs to `Release` the semaphore, as the OP does in their code sample. The interesting part, that could be posted as an answer to this question if it was still open, is that you can await for all tasks to complete by awaiting the semaphore (at the end) a number of times equal to the `initialCount` you passed in its constructor. – Theodor Zoulias Oct 21 '20 at 11:00

0 Answers0