使用多线程可能导致过多的内存使用 [英] Usage multithreading could lead to excessive memory use

查看:553
本文介绍了使用多线程可能导致过多的内存使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Windows服务项目,该项目将消息记录到数据库(或其他地方).这些消息的频率可能高达每秒十个.由于发送和处理消息不应延迟服务的主要过程,因此我启动了一个用于处理每条消息的新线程.这意味着,如果主进程需要发送100条日志消息,则会启动100个线程来处理每条消息.我了解到,线程完成后将被清理,因此我不必处理它.只要我将所有用过的对象放置在线程中,一切都应该可以正常工作.

I'm having a windows service project that logs messages to a database (or other place). The frequency of these messages could go up to ten per second. Since sending and processing the messages shouldn't delay the main process of the service I start a new thread for the processing of every message. This means that if the main process needs to send 100 log messages, 100 threads are started that process each message. I learned that when a thread is done, it will be cleaned so I don't have to dispose it. As long as I dispose all used objects in the thread everything should be working fine.

该服务可能会进入导致关闭该服务的异常.在服务关闭之前,它应该等待所有正在记录消息的线程.为此,它在每次启动线程时将线程添加到列表中.调用wait-for-threads方法时,将检查列表中的所有线程是否仍处于活动状态,如果存在,则使用join来等待它.

The service could go into a exception that leads to shutting down the service. Before the service shuts down it should wait for all threads that were logging messages. To achieve this it adds the thread to a list every time a thread is started. When the wait-for-threads method is called, all threads in the list are checked if it is still alive and if so, it uses join to wait for it.

代码:

创建线程:

/// <summary>
    /// Creates a new thread and sends the message
    /// </summary>
    /// <param name="logMessage"></param>
    private static void ThreadSend(IMessage logMessage)
    {
        ParameterizedThreadStart threadStart = new ParameterizedThreadStart(MessageHandler.HandleMessage);
        Thread messageThread = new Thread(threadStart);
        messageThread.Name = "LogMessageThread";            
        messageThread.Start(logMessage);
        threads.Add(messageThread);
    }

等待线程结束:

    /// <summary>
    /// Waits for threads that are still being processed
    /// </summary>
    public static void WaitForThreads()
    {
        int i = 0;
        foreach (Thread thread in threads)
        {
            i++;
            if (thread.IsAlive)
            {
                Debug.Print("waiting for {0} - {1} to end...", thread.Name, i);
                thread.Join();
            }
        }
    }

现在,我主要担心的是,如果该服务运行一个月,它将仍然在列表中包含所有线程(数百万个)(其中大多数已死).这会占用内存,我不知道要多少.总体而言,这对我来说似乎不是一个好习惯,我想清理完成的线程,但我不知道该怎么做.有没有人对此有好的或最佳的做法?

Now my main concern is if this service runs for a month it will still have all threads (millions) in the list (most of them dead). This will eat memory and I don't know how much. This in whole doesn't seem to be a good practice to me, I want to clean up finished threads but I can't find out how to do it. Does any one have a good or best practice for this?

推荐答案

由于多个答案和注释导致了我的解决方案,因此我将在此处发布完整的代码.

Since multiple answers and comments led to my solution I will post the complete code here.

我使用线程池来管理

I used threadpool to manage the threads and code from this page for the wating function.

创建线程:

private static void ThreadSend(IMessage logMessage)
        {    
            ThreadPool.QueueUserWorkItem(MessageHandler.HandleMessage, logMessage);
        }

等待线程完成:

public static bool WaitForThreads(int maxWaitingTime)
        {
            int maxThreads = 0;
            int placeHolder = 0;
            int availableThreads = 0;

            while (maxWaitingTime > 0)
            {
                System.Threading.ThreadPool.GetMaxThreads(out maxThreads, out placeHolder);
                System.Threading.ThreadPool.GetAvailableThreads(out availableThreads, out placeHolder);

                //Stop if all threads are available
                if (availableThreads == maxThreads)
                {
                    return true;
                }

                System.Threading.Thread.Sleep(TimeSpan.FromMilliseconds(1000));
                --maxWaitingTime;            
            }

            return false;
        }

您可以选择将其添加到这些方法之外的某个位置,以限制池中的线程数量.

Optionally you can add this somewhere outside these methods to limit the amount of threads in the pool.

System.Threading.ThreadPool.SetMaxThreads(MaxWorkerThreads, MaxCompletionPortThreads);

这篇关于使用多线程可能导致过多的内存使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆