2012-05-01 2 views
4

当社の製品(24時間365日稼働できるWindowsサービス)に第三者コンポーネントを追加する必要があります。
3PCは、画像を操作するためのいくつかのハードコアC++の美しさに乗っている.netライブラリです。
3PCが必要です初期化およびTeardownルーチンは、それが実行されるスレッドごとに呼び出されます。
これは古いソフトウェアで使用する場合は問題ありませんが、この製品は.Netスレッドプールで作成され、プールされた作業者は3PCを実行します。 初期化Teardownルーティンを安全に呼び出す方法がわかりません。 3PC Initializeメソッドを呼び出すために、ThreadStaticメンバーを初期化するとき プールされたスレッド(またはThreadStaticメンバ)がいつ破壊されるかを知りたいですか?

私が得た最も近い

は、しかし、私は Initializeがコールされたのと同じスレッド上で Teardownを呼び出すために管理することはできませんでした。

私がオブジェクトで呼び出さTeardownメソッドをファイナライズし、その後、Teardownがオブジェクトが静的にありませんスレッド、GC自身のファイナライズスレッドによって呼び出されます、オブジェクト内のInitializeTeardownをラップする場合(ファイナライザが実行する保証がないという事実はもちろんですが)。

はもちろん、私ははカバーの下スレッド、スレッドが破壊されたり作成される場合、またはとき私は見当がつかないを管理し、スレッドプールなど漏れた資源心配ので、私はどのくらいさっぱりだがサービスは一定期間にわたって漏洩する可能性があります。

誰でもいいですね。私が逃したものは何ですか?他に何か試してみませんか?
おかげ

更新

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

私は「メモリを解放します」と思っていますが、私は正直言って考えていません。 Reflectorでアセンブリを分割しようとしましたが、すぐにILからネイティブのマシンコードに落ちます。私はこれをやらなければならない(第3)党線に行くつもりです。

これは間違いなくサブシステムの破損物です。

また、数年前、私たちは別の製品でこのコンポーネントの周辺にバグを発見しました。初期化子は非常にまれにしか見られないいくつかのスレッドで呼び出されていない未定義の動作

+0

Initialize and Teardownの機能は何ですか?スレッドにとらわれない方法で安全に機能するように3PCライブラリを説得するのが最適でしょう。特に、「ティアダウン」は何をしていますか?それは、イメージ上のある/すべての操作の後に常に呼び出さなければならないのですか、それともサブシステムのシャットダウン/終了の問題でしょうか? –

+0

@Martin:質問に詳細を追加しました。 –

+2

スレッドプールで実行する作業単位の前後に 'Initialize'と' Teardown'を呼び出すことができますか? –

答えて

4

最悪が最悪になり、より良い解決策が出てこない場合は、固定数のスレッド(=コアの数?)で独自のスレッドプールを作成できます。各スレッドで3PCインスタンスを作成し、Initialize()を呼び出すことで、うまくいけばOKです。

ような何か: '新しいThreadPoolの(NumThreadsにする);' を呼び出し、それを起動する

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); 
    } 
}; 

} 

、シャットダウンするには、0に 'THREADCOUNT' プロパティを設定します。

+0

修正が適用されました - ctorで3PCが作成された元のコード - 作成スレッドによって呼び出されるため、これは機能しません。 run()メソッドの先頭にctor呼び出しを移動しました。 –

関連する問題