UWP handling many threads - c#

So I am developing a UWP application that has a large number of threads. Previously I would start all the threads with System.Threading.Tasks.Task.Run(), save their thread handles to an array, then Task.WaitAll() for completion and get the results. This currently is taking too much memory though.
I have changed my code to only wait for a smaller amount of threads and copy their results out before continuing on to more of the threads. Since UWP the UWP implementation of Task does not implement IDisposable, what is the proper way to signal the framework that I am done with a task so it can be garbage collected? I would like to read out the results of the treads after a certain number of them come in and dispose of the threads resources to make space for the next threads.
Thanks so much!

Just to point out an issue which might be degrading the performance of your application: You are deliberately blocking the thread until all Tasks complete rather than actually await for them. That would make sense, if you are not performing Asynchronous work inside them, but if you are, you should definitely switch to:
Task.WhenAll rather than Task.WaitAll , such as this:
List<Tasks> tasks = new List<Tasks> { Method1(), Method2(), ... };
Task result = await Task.WhenAll(tasks);
This way, you are actually leveraging the asynchrony of your app, and you will not block the current thread until all the tasks are completed, like Task.WaitAll() does.
Since you are utilizing the Task.Run() method, instead of the Task.Factory.StartNew(), the TaskScheduler used is the default, and utilizes Threads from the Thread Pool. So you will not actually end up blocking the UI thread, but blocking many Thread Pool threads, is also not good.
Taking from Microsoft documentation, for one of the cases where Thread Pools should not be used:
You have tasks that cause the thread to block for long periods of
time. The thread pool has a maximum number of threads, so a large
number of blocked thread pool threads might prevent tasks from
starting.
Edit:
I do not need anything else but I will look in to that! Thanks! So is
there any way I can get it to run the Tasks like a FIFO with just the
API's available with the default thread pool?
You should take a look, into Continuations
A continuation is nothing else other than a task which is activated whenever it's antecedent task/tasks have completed. If you have specific tasks which you only want to execute after another task has completed you should take a look into Continuations, since they are extremely flexible, and you can actually create really complex flow of Tasks to better suit your needs.

Garbage collection on a .Net application always works the same, when a variable is not needed anymore (out of scope) it is collected.
Why do you think the threads are consuming the memory? It is much likely than the process inside the threads is the one consuming the memory.

Related

Something wrong with parallel task execution along with Thread.Sleep [duplicate]

In C# 4.0, we have Task in the System.Threading.Tasks namespace. What is the true difference between Thread and Task. I did some sample program(help taken from MSDN) for my own sake of learning with
Parallel.Invoke
Parallel.For
Parallel.ForEach
but have many doubts as the idea is not so clear.
I have initially searched in Stackoverflow for a similar type of question but may be with this question title I was not able to get the same. If anyone knows about the same type of question being posted here earlier, kindly give the reference of the link.
In computer science terms, a Task is a future or a promise. (Some people use those two terms synonymously, some use them differently, nobody can agree on a precise definition.) Basically, a Task<T> "promises" to return you a T, but not right now honey, I'm kinda busy, why don't you come back later?
A Thread is a way of fulfilling that promise. But not every Task needs a brand-new Thread. (In fact, creating a thread is often undesirable, because doing so is much more expensive than re-using an existing thread from the thread pool. More on that in a moment.) If the value you are waiting for comes from the filesystem or a database or the network, then there is no need for a thread to sit around and wait for the data when it can be servicing other requests. Instead, the Task might register a callback to receive the value(s) when they're ready.
In particular, the Task does not say why it is that it takes such a long time to return the value. It might be that it takes a long time to compute, or it might be that it takes a long time to fetch. Only in the former case would you use a Thread to run a Task. (In .NET, threads are freaking expensive, so you generally want to avoid them as much as possible and really only use them if you want to run multiple heavy computations on multiple CPUs. For example, in Windows, a thread weighs 12 KiByte (I think), in Linux, a thread weighs as little as 4 KiByte, in Erlang/BEAM even just 400 Byte. In .NET, it's 1 MiByte!)
A task is something you want done.
A thread is one of the many possible workers which performs that task.
In .NET 4.0 terms, a Task represents an asynchronous operation. Thread(s) are used to complete that operation by breaking the work up into chunks and assigning to separate threads.
Thread
The bare metal thing, you probably don't need to use it, you probably can use a LongRunning task and take the benefits from the TPL - Task Parallel Library, included in .NET Framework 4 (february, 2002) and above (also .NET Core).
Tasks
Abstraction above the Threads. It uses the thread pool (unless you specify the task as a LongRunning operation, if so, a new thread is created under the hood for you).
Thread Pool
As the name suggests: a pool of threads. This is the .NET framework handling a limited number of threads for you. Why? Because opening 100 threads to execute expensive CPU operations on a Processor with just 8 cores definitely is not a good idea. The framework will maintain this pool for you, reusing the threads (not creating/killing them at each operation), and executing some of them in parallel, in a way that your CPU will not burn.
OK, but when to use each one?
In resume: always use tasks.
Task is an abstraction, so it is a lot easier to use. I advise you to always try to use tasks and if you face some problem that makes you need to handle a thread by yourself (probably 1% of the time) then use threads.
BUT be aware that:
I/O Bound: For I/O bound operations (database calls, read/write files, APIs calls, etc) avoid using normal tasks, use LongRunning tasks (or threads if you need to). Because using tasks would lead you to a thread pool with a few threads busy and a lot of other tasks waiting for its turn to take the pool.
CPU Bound: For CPU bound operations just use the normal tasks (that internally will use the thread pool) and be happy.
In addition to above points, it would be good to know that:
A task is by default a background task. You cannot have a foreground task. On the other hand a thread can be background or foreground (Use IsBackground property to change the behavior).
Tasks created in thread pool recycle the threads which helps save resources. So in most cases tasks should be your default choice.
If the operations are quick, it is much better to use a task instead of thread. For long running operations, tasks do not provide much advantages over threads.
A Task can be seen as a convenient and easy way to execute something asynchronously and in parallel.
Normally a Task is all you need, I cannot remember if I have ever used a thread for anything other than experimentation.
You can accomplish the same thing, with a thread (with lots of effort) as you can with a task.
Thread
int result = 0;
Thread thread = new System.Threading.Thread(() => {
result = 1;
});
thread.Start();
thread.Join();
Console.WriteLine(result); //is 1
Task
int result = await Task.Run(() => {
return 1;
});
Console.WriteLine(result); //is 1
A task will by default use the Threadpool, which saves resources as creating threads can be expensive. You can see a Task as a higher level abstraction upon threads.
As this article points out, Task provides the following powerful features over Thread.
Tasks are tuned for leveraging multicore processors.
If the system has multiple Tasks then it makes use of the CLR thread pool
internally, and so does not have the overhead associated with creating
a dedicated thread using the Thread. Also reduces the context
switching time among multiple threads.
Task can return a result. There is no direct mechanism to return the result from thread.
Wait on a set of Tasks, without a signaling construct.
We can chain Tasks together to execute one after the other.
Establish a parent/child relationship when one task is started from
another task.
A child Task Exception can propagate to parent task.
Tasks support cancellation through the use of cancellation tokens.
Asynchronous implementation is easy in Task, using async and
await keywords.
I usually use Task to interact with Winforms and simple background worker to make it not freeze the UI. Here is an example of when I prefer using Task.
private async void buttonDownload_Click(object sender, EventArgs e)
{
buttonDownload.Enabled = false;
await Task.Run(() => {
using (var client = new WebClient())
{
client.DownloadFile("http://example.com/file.mpeg", "file.mpeg");
}
})
buttonDownload.Enabled = true;
}
VS
private void buttonDownload_Click(object sender, EventArgs e)
{
buttonDownload.Enabled = false;
Thread t = new Thread(() =>
{
using (var client = new WebClient())
{
client.DownloadFile("http://example.com/file.mpeg", "file.mpeg");
}
this.Invoke((MethodInvoker)delegate()
{
buttonDownload.Enabled = true;
});
});
t.IsBackground = true;
t.Start();
}
the difference is you don't need to use MethodInvoker and shorter code.
You can use Task to specify what you want to do then attach that Task with a Thread. so that Task would be executed in that newly made Thread rather than on the GUI thread.
Use Task with the TaskFactory.StartNew(Action action). In here you execute a delegate so if you didn't use any thread it would be executed in the same thread (GUI thread). If you mention a thread you can execute this Task in a different thread. This is an unnecessary work cause you can directly execute the delegate or attach that delegate to a thread and execute that delegate in that thread. So don't use it. it's just unnecessary. If you intend to optimize your software this is a good candidate to be removed.
**Please note that the Action is a delegate.
Task is like an operation that you want to perform. Thread helps to manage those operation through multiple process nodes. Task is a lightweight option as Threading can lead to complex code management.
I suggest you read from MSDN (best in world) always Task
Thread

Are TAP and async/await meant to be used for dedicated threads?

I have some number of threads dedicated to one task (receive and handle requests) and some number of threads dedicated to other tasks (long running/CPU intensive tasks).
It's a console application.
And I want to use async/await in all of the threads but I learned that async/await uses the managed thread pool to run continuation that means requests handling can be delayed because of a bunch of CPU intensive tasks shown up (yes, so many, it's why i have limited threads count to do this job)?
If i want to limit concurrency, then i must not use TAP?
If i want to do some job in background for aplication's lifetime, then i must not use TAP either?
Should I write a ThradPool implementation with it's own SyncronizationContext to do so?
Is there an other way to run continuation in some set of threads?
And I want to use async/await in all of the threads but I learned that async/await uses the managed thread pool to run continuation that means requests handling can be delayed because of a bunch of CPU intensive tasks shown up (yes, so many, it's why i have limited threads count to do this job)?
This is a close-enough analysis. Technically, it's not async/await that needs the thread pool for continuations, but internal TAP method implementations. That said, it is a common pattern in the BCL, and because of this, exhausting the thread pool can cause delays for asynchronous completion.
If i want to limit concurrency, then i must not use TAP?
As long as you don't overwhelm the thread pool, you can use TAP. Limiting concurrency would free up the thread pool, which will enable TAP.
If i want to do some job in background for aplication's lifetime, then i must not use TAP either?
I would think of it more as "don't drown the thread pool in work". An exhausted thread pool isn't great for any kind of work.
Should I write a ThradPool implementation with it's own SyncronizationContext to do so?
Is there an other way to run continuation in some set of threads?
You can use SynchronizationContext to control where await resumes executing, but there are still BCL-internal completions that need to queue to the thread pool. There's no controlling that; the only real option is to keep the thread pool free.

How can I make a thread wait until another thread is wating (C#)

I have a consumer thread that creates some worker threads. These threads must switch between active and waiting states. When all worker threads are in the waiting states, it means that the current job is done. How can I make the consumer thread wait for all the worker threads to be in the waiting state? I want a behavior very similar to Thread.Join() on all worker threads, however, I want the threads to keep running for the next job. I cannot create new threads because the jobs are in a tight loop and creating new threads is costly.
As far as I am aware there is no mechanism to do what you wish. (Thread.Join but since you can't block that is not an option)
From the info you provided it sounds like your really building a state machine, just across multiple threads.
I would create a Singleton and have that act as a state machine. Threads could signal to the Singleton there status.
It sounds like you have an indeterminate number of threads, so you would need to put the status of each in a collection. I would look here Thread Safe Collections to find the right fit for how you wish to store your state information.
Hope this helps.
Apologies for the brief answer (may expand later), but you probably the WaitHandle.WaitAll method, combined with a ManualResetEvent. You would pass your ManualResetEvent objects into each worker thread when they're created, signal them when they become idle, and pass the entire set of handles into the WaitHandle.WaitAll method to wake the observing thread when they're complete. You can also use the timeout feature of this method if you want to periodically run some kind of task while waiting, or perform some kind of operation if the task is taking too long.
Note that if your worker threads are intended to terminate when the operation is complete (wasn't totally clear if this is the case), it might be more appropriate to spawn them as tasks and use Task.WaitAll instead.
Edit: On a quick re-read, it sounds like you do want to be using tasks rather than trying to re-use full worker threads. Tasks use threads which have been allocated from the thread pool, eliminating that thread creation overhead you were worried about, because the threads will (generally) be ready and waiting for work. You can simply spawn each task and wait for them all to be finished.

Is there a use case where tasks perform worse than threads?

It is considered that tasks are usually better choice than threads as they avoid wasting OS threads and give more programmatic control, but I wonder is there actually a use case where tasks performs worse than threads (so threads should be used instead)?
A task, when is about to be executed, will be executed in a thread context. A thread from the .NET thread pool will be used for the execution of a task. That being said there isn't any comparison between them.
Specifically, a task will be assigned to a thread of the thread pool to be executed, provided that there is a free thread. If there isn't any available thread, then the task will be placed in a queue waiting for one of the used threads to be free and it will be assigned to this thread (if the task is the first in the queue...). If the task will wait a long time in the queue (there is a specific time interval for this, but I don't remember it at this moment), then a new thread will be created, in order to service this task.

Can .NET Task instances go out of scope during run?

If I have the following block of code in a method (using .NET 4 and the Task Parallel Library):
var task = new Task(() => DoSomethingLongRunning());
task.Start();
and the method returns, will that task go out of scope and be garbage collected, or will it run to completion? I haven't noticed any issues with GCing, but want to make sure I'm not setting myself up for a race condition with the GC.
Update:
After I answered this question (a long time ago!) I found out that it's not true that Tasks will always run to completion - there's a small, let's say "corner" case, where tasks may not finish.
The reason for that is this: As I have answered previously, Tasks are essentially threads; but they are background threads. Background threads are automatically aborted when all foreground threads finish. So, if you don't do anything with the task and the program ends, there's a chance the task won't complete.
You should always await on tasks. More information can be found on the excellent answer Jon gave me.
Original:
Task are scheduled to the ThreadPool, meaning that they are essentially threads¹ (actually, they encapsulate threads).
From the Thread documentation:
It is not necessary to retain a
reference to a Thread object once you
have started the thread. The thread
continues to execute until the thread
procedure is complete.
So, no, there is no need to retain a reference to it.
Also, the documentation states that the preferred way to create a Task is to use it's factory:
You can also use the StartNew method
to create and start a task in one
operation. This is the preferred way
to create and start tasks if creation
and scheduling do not have to be
separated (...)
Hope it helps.
¹ Accordingly to the documentation:
A task represents an asynchronous
operation, and in some ways it
resembles the creation of a new thread
or ThreadPool work item, but at a
higher level of abstraction.
The task will run to completion. Even if there aren't any other references to it (not being rooted I believe is the term), the thread pool will still hold a reference to it, and prevent it from being Garbage Collected at least (I say at least, because even after it completes, there is no guarantee that it will be Garbage Collected) until completion.

Categories