0

I've a scheduled task in my ASP.NET MVC site that nightly sends notifications for the users.

I've been sending and awaiting notifications one by one, but it's taking an hour to complete now, so I thought I should send them in batches.

int counter = 0;
List<Task> tasks = new List<Task>();

foreach (var user in users)
{
    tasks.Add(Task.Run(async () =>
    {
        await user.SendNotificationAsync();
        counter++;
    }));

    if (tasks.Count >= 20)
    {
        await Task.WhenAll(tasks);
        tasks.Clear();
    }
}

if(tasks.Any())
{
    await Task.WhenAll(tasks);
    tasks.Clear();
}

But I've read that creating multiple threads is not efficient on the servers. How should I run multiple instances of the method on the server?

9
  • Or maybe because this is just a single scheduled task, has not a big effect on the server and is alright already? Commented Oct 23, 2017 at 0:40
  • "How should I run multiple instances of the method on the server?" How do you expect to do this without multiple threads? Commented Oct 23, 2017 at 0:42
  • @CamiloTerevinto But multiple threads are evil. some way other than that maybe? Commented Oct 23, 2017 at 0:43
  • Evil to who? That's the most weird comment I've read on this site. Did you know that processors are advancing towards more cores instead of more power per core? That's a 90's way of thinking. Commented Oct 23, 2017 at 0:45
  • I think its fine. its not like running multiple thread for long time simultaneously. It only does its simple job and discarded. Commented Oct 23, 2017 at 0:46

2 Answers 2

3

Because you are not following the best practices on TPL, here's a rewrite on how you should do it:

List<Task> tasks = new List<Task>();
int counter = 0; // not sure what this is for

foreach (var user in users)
{
    tasks.Add(user.SendNotificationAsync()); // do not create a wrapping task
    counter++; // not sure about this either

    // it won't ever be greater than 20
    if (tasks.Count == 20)
    {
        await Task.WhenAll(tasks);
        tasks.Clear();
    }
}

if (tasks.Any())
{
    await Task.WhenAll(tasks);
    tasks.Clear();
}

This is perfectly fine, also, because threads will be spawned and destroyed as soon as they are done.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. (that counter is to inform me later how much notifications are sent)
@Enigmativity thanks, I normally confuse them, not native language
1

Just to shed light on what Camilo meant by his example was that, in your example, you were creating a new Task to monitor your awaitable task. So, essentially, you were not only creating twice the number of tasks needed, you were also chaining them up - a Task to monitor a Task, where the middle task is just a proxy which will be picked up from the Threadpool just to monitor another task from the Threadpool.

As the user.SendNotificationAsync() is an awaitable task anyway, you can directly add it to the List<Task> - tasks and await directly on it.

Hence his example.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.