views:

64

answers:

5

Hi,

I have an application (.Net 3.5) which creates threads to write something to the database so that the GUI does not block. All created threads are added to a list, so that I can wait (Thread.Join) for each thread when the application is closed (maybe not all threads are finished when the application is closed, so the app must wait for them). Because of the list I get some serious problems if there are too many threads created (OutOfMemoryException). I tried removing finished threads from the list, but somehow that didn't work. Are there better ways to manage a list of threads, so I can remove them once they are finished?

Edit: It seems that fixed it (called whenever a thread is added):
lock (m_threadLock)
{
m_threads.RemoveAll(x => x.ThreadState == ThreadState.Stopped);
}

+2  A: 

How about System.Threading.ThreadPool and SetMaxThreads plus QueueUserWorkItem?

http://msdn.microsoft.com/en-US/library/system.threading.threadpool%28v=VS.80%29.aspx

AOI Karasu
I dont think OP is using the ThreadPool.
Aseem Gautam
All threads in the threadpool are background threads and I cannot wait for them (isn't supported) when the application is closed. But I must wait for them to be finished.
Satanlike
How about intercepting the app's close event and wait until GetMaxThreads == GetAvailableThreads? You can even let the GUI hide and hold the process until the job is done.
AOI Karasu
A: 

Not sure if this is what you want, but how about something like this?

Action foo = () =>
{
    Thread.Sleep(1000);
};

var handles = new List<WaitHandle>();
for (int i = 0; i < 10; i++)
{
    var result = foo.BeginInvoke(r =>
    {
        foo.EndInvoke(r);
    }, null);
    handles.Add(result.AsyncWaitHandle);
}

WaitHandle.WaitAll(handles.ToArray());
Will Vousden
A: 

OutOfMemoryException doesn't seem like the sort of thing that would be caused by the list of threads - more likely it's because of the threads themselves, ie. you are creating too many of them. You need to re-use existing ones and wait for them to become available if there are too many already. This is exactly what a thread pool does. If the built-in .NET one doesn't support waiting for the threads then you'll just have to find a third-party implementation or, worst come to worst, write your own - possibly using the built-in one as a guide.

Evgeny
I've written my own implementation once, and it still works fine in quite large environment, but it was a real pain to test it and consumed fair amount of time. I'd recommend ThreadPool.
AOI Karasu
ThreadPool==Background threads. Not the solution.
Henk Holterman
+1  A: 

You cannot keep on creating new threads while keeping a hold on the old ones, you'll run out of memory.

I tried removing finished threads from the list, but somehow that didn't work.

That is the right path, why didn't it work?

  1. Add code to your thread-methods to signal completion (maybe remove themselves from the list).
  2. Look for a custom ThreadPool. There are several implementations published. You can use a simple one and control Background=false and other details.
Henk Holterman
I developed this application at least one year ago (with C# 2.0), so I cannot tell what the problem was. I am testing with this for now, maybe that works: m_threads.RemoveAll(x => x.ThreadState == ThreadState.Stopped);
Satanlike
A: 

Use a more advanced ThreadPool, like this one: http://www.codeproject.com/KB/threads/smartthreadpool.aspx . It allows you to cancel work items or wait for all work items to complete.

Catalin DICU