2012-10-19 10 views
5

スレッドでバックグラウンドでプロキシを開こうとしていますが、スレッドはプロキシの新しいインスタンスを作成し、サービスのメソッドを呼び出し、サービスを破棄します。スレッドで複数のサービスを開始する

このすべてがスレッド上で起こる:

var background = new Thread(() => 
{ 
    var proxy = new AssignmentSvcProxy(new EndpointAddress(worker.Address));    

    try 
    { 
     proxy.Channel.StartWork(workload); 
     proxy.Dispose();     
    } 
    catch (EndpointNotFoundException ex) 
    { 
     logService.Error(ex);       
     proxy.Dispose(); 
     proxy = null; 
    } 
    catch (CommunicationException ex) 
    { 
     logService.Error(ex); 
     proxy.Dispose(); 
     proxy = null; 
    } 
    catch (TimeoutException ex) 
    { 
     logService.Error(ex);      
     proxy.Dispose(); 
     proxy = null; 
    } 
    catch (Exception ex) 
    { 
     logService.Error(ex);      
     proxy.Dispose(); 
     proxy = null; 
    }     

}) { IsBackground = true }; 

background.Start(); 

私はCloseTimeoutこのため、最大、です。OpenTimeout、ReceiveTimeoutという、SendTimeoutにタイムアウトを設定しているにもかかわらず起こって断続的にタイムアウトの問題を見ておきます。

私はちょうどこれが問題ではないことを賢明に考えています。すなわち、スレッド上でサービスを開き、それを廃棄することです。

EDIT:

プロキシは、内部でスレッドごとに異なるエンドポイントにカスタムバインディングを持つチャネルを確立します。

+0

それはあなたが、例えば、私は「プロキシ」(あるいは「クライアント」)を期待する「サービス」について話すことに少し混乱だが"スレッドはサービスを開きます" "スレッドは私のサービスのためのプロキシを開く"でなければなりません。 – Jeroen

+0

申し訳ありませんが、質問を更新しましたので、基本的に私のサービスは既に開いていますが、プロキシは単にproxy.Channel.StartWork(ワークロード)を呼び出します。その特定のサービス(すでに自己ホストされています)の意味がわかりますか? –

+0

あなたのtry-catch句に 'finally'を追加したいかもしれません。例外がスローされても最後にコードを実行します。あなたの問題に関しては、私は不確実です。私はまた、あなたのバインディングをコンストラクタに渡すことが賢明かもしれないと信じています。これがタイムアウト例外の原因になっている可能性があります。 –

答えて

6

プロキシを正しく閉じていないという問題が考えられます。多くのスレッドがサーバーに当たっていて、それ以降にすべてがクリーンアップされていない場合は、それらの接続でタイムアウトが発生することがあります。

廃棄は接続を閉じるのには適していません。ここでの詳細情報:Disposing proxies

次のように使用するのに理想的なパターンは次のとおりです。

try 
{ 
    proxy.Close(); 
} 
catch (Exception ex) 
{ 
    proxy.Abort(); 
} 
finally 
{ 
    proxy = null; 
} 

あなたはそれが失敗した場合、あなたはすべての接続を中止し、接続を終了しようとします。例外がある場合、Disposeは中断しません。

そのように、私はそうのようにリファクタリングします:

var background = new Thread(() => 
{ 
    var proxy = new AssignmentSvcProxy(new EndpointAddress(worker.Address));    

    try 
    { 
     proxy.Channel.StartWork(workload); 
    } 
    catch (Exception ex) 
    { 
     // You aren't doing anything special with your specific exception types 
     logService.Error(ex);      
    }     
    finally 
    { 
     try 
     { 
      proxy.Close(); 
     } 
     catch (Exception ex) 
     { 
      proxy.Abort(); 
     } 
     finally 
     { 
      proxy = null; 
     } 
    } 

}) { IsBackground = true }; 

background.Start(); 
+1

これは機能します。ただし、WCFプロキシはスレッドセーフです(同時呼び出しはシリアライズされます)。プロキシの作成とサーバーへの新しい接続のオープンはコストがかかるため、通常はプロキシはスレッド間で再利用されます。 –

+0

私は同意します。なぜなら、何らかの理由で接続が失敗した場合に、理想的には再試行の仕組みを持っているべきだからです。これにより、障害処理におけるこのパターンは、新しい接続を強制的に作成する前に、古い接続を確実にクリーンアップします。 – Bardia

関連する問題