4

サードパーティのコンポーネントを製品の1つに追加する必要があります(これは24時間年中無休で実行できるWindowsサービスです)。
3PCは、画像を操作するためのハードコアC++の可愛らしさの上にある.netライブラリです。
3PCでは、実行するスレッドごとにInitializeルーチンとTeardownルーチンを呼び出す必要があります。
これは、古いソフトウェアで使用する場合は問題ありませんが、この製品は.Netスレッドプールを使用して作成されており、プールされたワーカーは3PCを実行します。InitializeルーチンとTeardownルーチンを安全に呼び出す方法がわかりません。

私が得た最も近いのは、ThreadStaticメンバーを初期化して、3PCメソッドを呼び出すときでしたが、呼び出されたのと同じスレッドでInitializeを呼び出すことができません。TeardownInitialize

InitializeTeardownをオブジェクトでラップTeardownし、オブジェクトのFinalizeメソッドで呼び出されると、オブジェクトが静的なスレッドTeardownではなく、GC自体のFinalizeスレッドによって呼び出されます(ファイナライザーの保証がないことは言うまでもありません)。実行されます)。

明らかに、スレッドプールが内部でスレッドを管理しているため、リソースのリークが心配です。スレッドが破棄または作成されるかどうか、いつ作成されるかわからないため、サービスが一定期間にどれだけリークする可能性があるかわかりません。 。

誰かアイデアはありますか?私が見逃したものはありますか?他に試すことはありますか?
ありがとう

アップデート

Q:ティアダウンは何をしますか?

「記憶を解放する」と思いますが、正直わかりません。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 に答える