简体   繁体   中英

Informing ThreadPool.QueueUserWorkItem about memory requirements

We are designing an application where users can set multiple tasks running simultaneously. We use ThreadPool.QueueUserWorkItem to set the tasks running. That part runs well.

We do have a problem where these tasks can consume 500MB+ of memory. We are using memory-mapped I/O to manage the memory. Still when users set 10+ tasks running simultaneously, the threadpool will start all of them and there have been times that we run out of memory and exceptions occur. We can handle the errors just fine.

What I am wondering is if there is a way to take the memory that will be consumed into account when processing the queue, ie keeping tasks queued until sufficient memory exists? Can I inform the threadpool about how much memory we will be asking for (which we can roughly estimate)?

The ThreadPool knows nothing about what you do in your tasks. You need to ensure this yourself. You can manage a global variable of type long representing the total amount of bytes that all running jobs are likely to need at peak. When the threadpool schedules one of your tasks, you first check that variable. If it is already too high you wait until any task that is currently running has exited. Then you check again.

A low-tech solution to this is to use polling with 100ms sleep interval. A high-tech version would use some kind of waiting scheme involving events.

OK, if you can get a memory estimate for each task, you could probably do this by keeping a rough CS-protected count of memory usage in the pool. Add to this count just before a task is submitted and have the task call a 'memRelease' function to subtract from it just before it ends and check to see if anything can be run now, (see later).

If some thread wants to submit a task and it is found, (by comparing its needs with the current usage inside the CS), that there is insufficient memory left in the 'budget' to run it, you could shove it into a concurrent queue/list to wait until there is. Whenever a task completes and calls 'memRelease', it adds to the memory buget and iterates the queue/list, (locking it first), to try an find something that can now be run with the increased memory available. If so, it submits the task to the pool.

You can control number of threads in thread pool by ThreadPool.SetMaxThreads. So what you can do is to set your max number of threads

ThreadPool.SetMaxThreads = new PerformanceCounter("Memory", "Available MBytes").RawValue / 500;

PerformanceCounter("Memory", "Available MBytes").RawValue -> Returns available memory in MB

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM