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

时间:2012-05-01 15:08:19

标签: .net multithreading .net-3.5 threadpool

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

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

如果我将InitializeTeardown包装在一个对象中,并在对象Finalize方法中调用Teardown,那么Teardown将由GC自己调用完成线程,而不是线程对象是 static (更不用说不能保证Finalizer将会运行)。

显然我担心泄露的资源,因为线程池管理线程,我不知道线程是否会被销毁或创建,所以我不知道服务在一段时间内会泄漏多少。

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

更新

问:拆解做什么?

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

这肯定是一个子系统拆解的事情。

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

1 个答案:

答案 0 :(得分: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。