首页 文章

无论如何要知道何时销毁一个池化线程(或ThreadStatic成员)?

提问于
浏览
4

我需要在我们的某个产品中添加第三方组件(这是一个可以全天候运行的Windows服务) .
3PC是一个.net库,它位于一些硬核C可操作图像上 .
3PC要求为其运行的每个线程调用Initialize和Teardown例程 .
这在我们的旧软件中使用它很好,但是这个产品是用.Net线程池编写的,汇集的工作人员将使用3PC . 我无法弄清楚如何安全地调用Initialize和Teardown例程 .

我得到的最接近的是初始化ThreadStatic成员,调用3PC Initialize 方法,但是我无法在调用 Initialize 的同一线程上调用 Teardown .

如果我将 InitializeTeardown 包装在一个对象中,并在对象Finalize方法中调用 Teardown ,那么 Teardown 将由GC自己的Finalize线程调用,而不是该对象静态的线程(更不用说有这样的事实)不保证Finalizer会运行) .

显然我担心泄漏的资源,因为线程池管理线程下的线程,所以我不知道服务在一段时间内会泄漏多少 .

任何想法?我错过了什么?还有别的尝试吗?
谢谢

Update

问:拆解有什么作用?

我假设它“释放一些记忆”,但老实说我不知道 . 我尝试使用Reflector通过程序集进行splunking,但很快就从IL中删除了本机代码 . 我要去(第三)党派,必须这样做 .

它绝对是一个子系统拆解的东西 .

此外,几年前我们在另一个产品中发现了这个组件的错误 . 没有为每个线程调用初始化程序,导致一些非常罕见的未定义行为 .

1 回答

  • 4

    如果最糟糕的情况发生,并且没有更好的解决方案即将到来,您可以使用固定数量的线程创建自己的线程池(=内核数量?) . 通过在每个线程中创建一个3PC实例并调用Initialize(),您应该可以 .

    就像是:

    using System;
    using System.Collections.Generic;
    using System.Collections.Concurrent;
    using System.Linq;
    using System.Text;
    using System.Threading;
    
    namespace WindowsPoolApp
    {
    
    
    public abstract class Task {
        public EventHandler FonComplete;
        public ThreadPool myPool;
        protected int param;
        public Exception error;
        public Task(int inParam, EventHandler OnDone) { param = inParam; FonComplete = OnDone; }
        public abstract void run();
    };
    
    public class PoolThread{
    private
        3PC my3PC;
        BlockingCollection<Task> FinQueue;
    public
        PoolThread(BlockingCollection<Task> inQueue)
        {
           FinQueue=inQueue;
        }
        Task inMess;
        public void run(){
            my3PC = new 3PC();
            my3PC.Initialize();
            while(true){
                inMess=FinQueue.Take();
                if(inMess==null){
                  my3PC.Teardown();
                  return;
                }
                try
                {
                    inMess.run();
                    inMess.error = null;
                }
                catch (Exception e)
                {
                    inMess.error = e;
                }
                inMess.FonComplete(inMess, null);
            }
        }
    };
    
    public class ThreadPool {
        volatile int FthreadCount;
        BlockingCollection<Task> queue;
        void startThread(){
                PoolThread thisPoolThread=new PoolThread(queue);
                Thread thisThread=new Thread(new ThreadStart(thisPoolThread.run));
                thisThread.Priority = ThreadPriority.BelowNormal;
                thisThread.IsBackground = true;
                thisThread.Start();
        }
        void SetThreadCount(int newCount){
            while(FthreadCount<newCount){startThread();};
            while(FthreadCount>newCount){
                queue.Add(default(Task));
                FthreadCount--;
            };
        }
        public ThreadPool(int initThreads){
            queue=new BlockingCollection<Task>();
            for(FthreadCount=0;FthreadCount<initThreads;FthreadCount++) startThread();
        }
        public int threadCount{
            get{return FthreadCount;}
            set
            {
                while (FthreadCount < value) {
                    startThread();
                    FthreadCount++;
                };
                while (FthreadCount > value)
                {
                    queue.Add(default(Task));
                    FthreadCount--;
                }
            }
        }
    
        public void submit(Task task){
            task.myPool=this;
            queue.Add(task);
        }
    };
    
    }
    

    要启动它,请调用'new ThreadPool(numThreads);',要关闭,请将'threadCount'属性设置为0 .

相关问题