4

我需要将第三方组件添加到我们的一个产品中(这是一个可以 24/7 运行的 Windows 服务)。
3PC 是一个 .net 库,它具有一些用于处理图像的硬核 C++ 可爱。
3PC 要求为它运行的每个线程调用InitializeTeardown例程。
这很好,我们在旧软件中使用它,但这个产品是用 .Net 线程池编写的,池化的工作人员将使用 3PC。我不知道如何安全地调用InitializeTeardown例程。

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

Initialize如果我将and包装Teardown在一个对象中,并在对象中Teardown调用 Finalize 方法,那么Teardown将由 GC 自己的 Finalize 线程调用,而不是对象是静态的线程(更不用说不能保证 Finalizer 的事实将永远运行)。

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

有人有什么想法吗?我错过了什么?还有什么要尝试的吗?
谢谢

更新

问:拆解是做什么的?

我假设它“释放一些记忆”,但老实说我不知道​​。我尝试使用 Reflector 对程序集进行扩展,但它很快从 IL 变成了本机机器代码。我要坚持(第三)党路线,必须这样做。

这绝对是一个子系统拆除的事情。

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

4

1 回答 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。

于 2012-05-01T16:41:14.713 回答