4

My app does a lot of background tasks, and for each such action, I created a new thread for each action

Thread StreamResponse = new Thread(() => 
    {
        DB.ToDb(flag);
    });
StreamResponse.Start();

These actions take place thousands per minute. Noticed that the app starts eating RAM. That's normal, because the application creates thousands of threads and not closing them.

From here there is a question, how do I make it so that these actions were in a separate thread. For example, I create a thread in a separate class and in this thread commit acts.

Or otherwise can? The task that the thread was made and after the completion of the action is automatically closed. But perhaps more correctly just all these steps to do in another thread. What do you think? How to make?

May be using Dispatcher.BeginInvoke ?

T.S.
  • 18,195
  • 11
  • 58
  • 78
alexander
  • 195
  • 3
  • 13
  • 3
    Dispatcher is only for UI thread, meaning stuff which happens on UI elements like button. Please read about TPL, and you can you use await, asnyc and Task.run() – Gilad Jun 25 '15 at 21:56
  • Do you mean, `var worker = new Worker(); Thread t = new Thread(() => worker.DoWork(); t.IsBackground = true; t.Start();` ? – T.S. Jun 25 '15 at 21:58
  • I'd look into using the thread pool rather than creating 'thousands of threads'. In particular, look at higher level abstractions on top of that (TPL and async/await). – Charles Mager Jun 25 '15 at 22:00
  • Why are your threads running for such a long time. Are they waiting or doing slow IO? If not your system seems very overloaded. – usr Jun 25 '15 at 22:44
  • @usr Because I will not close?) – alexander Jun 25 '15 at 23:06
  • @Gilad thanks, will remember – alexander Jun 25 '15 at 23:08
  • That comment does not help address what I want to know. What are all those threads doing? Waiting? – usr Jun 25 '15 at 23:13
  • @usr I can't say exactly, but memory for an application increases with each passing second. Streams created a large number. The application starts using about 4.5 GB of memory and hangs. I did not know what the problem is. But then I realized that it may be associated with these threads that are created. – alexander Jun 25 '15 at 23:20
  • Use Process Explorer to monitor the number of threads (add it as a column). Confirm, that the number is rising. Wait until there are hundreds. Then, pause the debugger and look at what most threads are doing. Likely, they will be doing similar things. You now should know what they spent their time with. Is it IO? Like an HTTP call? Post information about what's going on. – usr Jun 26 '15 at 07:38
  • @usr I'm using WPF. I work with information that comes into the application. The information comes through an event in which a method is executed. Here I run this method in a new thread. A lot of information arrives. Thanks for the tip on the columns in task Manager. Did not know about this. Unfortunately, I can check it only next week. Be sure to write here about the results. – alexander Jun 26 '15 at 12:32
  • @usr http://f6.s.qip.ru/twYEFLC7.png This is what happened. – alexander Jul 02 '15 at 19:34

2 Answers2

4

It seems that you could benefit from using the ThreadPool Class. From MSDN:

Provides a pool of threads that can be used to execute tasks, post work items, process asynchronous I/O, wait on behalf of other threads, and process timers.

Here is a sample code for using it:

ThreadPool.QueueUserWorkItem((x) => 
{
    DB.ToDb(flag);
});

And you can set the maximum number of concurrent threads available in the thread pool using the ThreadPool.SetMaxThreads Method in order to improve performance and limit memory usage in your app.

Thomas C. G. de Vilhena
  • 13,819
  • 3
  • 50
  • 44
  • 2
    Doesn't help because apparently he produces thousands of *parallel* threads/tasks. They will be severely throttled by the pool and the pool will be overloaded at the same time which brings the rest of the app down. – usr Jun 25 '15 at 22:44
  • @usr: Indeed, the thread pool has limited "parallelism" and is best suited for processing a large amount of short tasks, since it reduces the overhead of creating and killing individual threads. I guess *alexander* would only benefit from using the thread pool if his tasks didn't require "independent" threads to execute. – Thomas C. G. de Vilhena Jun 26 '15 at 14:11
0

Why not use task factory?

  var task = Task.Factory.StartNew(()=>{ /*do stuff*/ });

Task factory works the same way as Queue does but has the advantage of allowing you to handle any return information more elegantly

 var result = await task;

The Factory will only spawn threads when it makes sense to, so essentailly is the same as the thread pool

If you want to use schedule longer running tasks this is also considered the better option, in terms of recommended practices, but would need to specify that information on the creation of the task.

If you need further information on there is a good answer available here : ThreadPool.QueueUserWorkItem vs Task.Factory.StartNew

Community
  • 1
  • 1
konkked
  • 3,161
  • 14
  • 19
  • Task factory will have to wait for the previous to do the following? The problem is that the action makes the contribution of information in different tables of the database. Accordingly, the action can be made slowly. No? – alexander Jun 25 '15 at 23:02
  • @alexander if you need the information back you can await, otherwise fire and forget, updated the answer to give a reference how to handle longer running tasks – konkked Jul 07 '15 at 18:29