2

I am trying to make some code run multithreaded using SemaphoreSlim and Task.Run().

Here is the snippet:

var semaphore = new SemaphoreSlim(50, 50);
foreach (var item in collection)
{
    semaphore.Wait();

    Task.Run(() =>
    {
        item.Property = DoTheThing(item.AnotherValue).Result;
        db.SaveChanges();
        semaphore.Release();
    });
}

What I expected to happen is that 50 tasks would be queued up and then semaphore.Wait() would kick in and hold the foreach loop until some tasks complete and semaphore.Release() frees up the threads so more can be queued.

What actually happens is the code runs synchronously one after the other. What am I missing here? I thought Task.Run() launched the lambda code on a new thread?

Guerrilla
  • 13,375
  • 31
  • 109
  • 210
  • 1
    `Task.Run()` returns a `Task` object, which you are not waiting on. – siride Oct 08 '16 at 23:10
  • @siride exactly, i am using SemaphoreSlim to control how many tasks get started. I am using this pattern with non-lambda expression and it works but with lambda expression it doesn't work for some reason and only single thread runs – Guerrilla Oct 08 '16 at 23:12
  • 1
    @Guerrilla: I'm still new to this, but I think then what you may want is to create an array of tasks and then use `Task.WhenAll()` on that array. You can do the semaphore wait within the lambda. – siride Oct 08 '16 at 23:14
  • ... or `Task.WhenAny()`, depending on what you are trying to do. – sstan Oct 08 '16 at 23:16
  • 1
    Lol at people voting to close because this is not related to programming. I managed to figure it out, the documentation doesnt show this on example but it needs to be called like `Task.Run( async () => { lambda } );` – Guerrilla Oct 08 '16 at 23:19
  • I did not vote to close! I think it's a legitimate question. You should post that as an answer. I would also try working in the `WhenAll()` business. – siride Oct 08 '16 at 23:21
  • 1
    *Lol at people voting to close because this is not related to programming*: No one did that. Yes, there are some close votes, but not for that reason. – sstan Oct 08 '16 at 23:43
  • @sstan "This question does not appear to be about programming within the scope defined" 2 x votes. – Guerrilla Oct 08 '16 at 23:46
  • 1
    @Guerilla: Ah, I see. That's misleading. If you drill down deeper into the subcategories, you'll see that the actual reason is not that at all. – sstan Oct 08 '16 at 23:55
  • @sstan ahh didnt realise there was sub-cats – Guerrilla Oct 09 '16 at 00:04

1 Answers1

0

Take a look at here: When would I use Task.Yield()?

Essentially Task.Run() does not guarantee that the code in it runs asynchronously. If you want to ensure that you have to do this:

Task.Run(async ()
{
    await Task.Yield();
    ...
});
Community
  • 1
  • 1
haindl
  • 3,111
  • 2
  • 25
  • 31
  • "does not guarantee that the code in it runs asynchronously" That doesn't sound right. From the docs on Task.Run: "Queues the specified work to run on the thread pool and returns a Task object that represents that work." – Max Barraclough Jun 25 '18 at 15:06