2016-08-11 11 views
0

スレッドセーフではありませんが、他のスレッドセーフでない外部リソースは使用しないライブラリを使用しています。スレッドセーフなライブラリを使用するためのクイックフィックス

スレッドセーフ(スレッドセーフではない主な理由は、インスタンスごとに読み取り/書き込みを行う静的フィールドが多く、処理される多くのインスタンスで正常に動作することですシーケンシャルに複数のインスタンスを並列に使用すると明らかに失敗します)

私はハックを感じる迅速な修正として、このアプローチを本質的に間違っているのだろうかと思っています。

スレッドごとにアプリケーションドメインを作成し、そのドメインにスレッドデータをマーシャリングし、各ドメインでライブラリを読み込み、スレッドを持つアプリケーションドメインを実行してから、アンロードします。

これは、減速(多くのライブラリがロードされ、背中合わせの力がたくさんあります)を意味していますが、これを不可能にする明白なものがあります。

+0

スピンのコストで暮らせるなら、アプリドメインをアップする。これが全体的に有益であるかどうかを知ることは興味深いでしょう。 – Biscuits

+0

@Biscuits今日の各通話のコストはかなり高くなります(人間の言葉では「長い」ではありませんが、5秒から1分の間の入力に応じて低レベルの言葉ではまだまだ巨大です)。一方、ライブラリとの間でやりとりするデータの量は少ないので(数KB程度)、appdomainの作成/削除やデータのマーシャリングのコストは、ターゲットハードウェア上でそれらを順番に大量に実行する必要があります。ちょうど私が愚かな道を取っていないことを確認しようとしている私は決してその解決策を見たことがない前に –

+0

あなたがしようとしているのはスケールアウトです。これはまれではありません。 IISは、アプリケーションプール上のワーカープロセスをバンプアップするときにこれを行います。実現する重要なことは、インプロセスでライブラリを呼び出すために追加コストがかかるIPCの形式が必要であり、できるだけ多くのライブラリを持たせて再利用することが有益であることを制限するスマートな方法が必要だということですプールで。実際には、あなたの戦略を策定するためにWebサーバから学ぶことがたくさんあります。 – Biscuits

答えて

0

どのくらいのライブラリと対話する必要がありますか?あまりにも巨大ではない場合は、その周りにラッパーを構築することができます。ラッパーのメソッドを呼び出すと、ロックを処理し、内部ライブラリへのスレッドセーフな呼び出しを行います。

インターフェイスを宣言することができ、実装はラッパークラスです。現在、スレッドの安全性の問題を解決することに加えて、静的メソッドへのテスト可能でない直接の依存関係を削除しました。

静的メンバーの別々の「インスタンス」を保持するだけのアプリドメインを作成するよりもはるかに洗練されたものになるでしょう(ライブラリによっては可能です)。

// Class with static memebers 
public class FooManager 
{ 
    public static void ManageFoo(Foo foo) 
    { 
     // Does some non thread-safe stuff 
    } 
} 

public interface IFooManager 
{ 
    void ManageFoo(Foo foo); 
} 

public class FooManagerWrapper : IFooManager 
{ 
    private static readonly object FooManagerLock = new object(); 

    public void ManageFoo(Foo foo) 
    { 
     lock (FooManagerLock) 
     { 
      FooManager.ManageFoo(foo); 
     } 
    } 
} 

This blog postが含まれています。スレッドの安全性が問題ではない場合でも、私は自分のコードが静的なクラスとメソッドに直接依存することは望ましくありません。(私がそれらを書いたとしても)

+1

しかし、これでロックしていると並列化する利点がなくなり、一度にN個のスレッドがN個ではなくN個のスレッドが一度に1つずつ動作することになります。私が望むのは、ライブラリ全体を修正することなく、マルチスレッドのパフォーマンスを向上させることです。 –

+0

これは依存しています - あなたの並列操作が行っている唯一のことがこのライブラリを使用している場合、それは非常に有益ではありません。しかし、他の操作が続いている場合、いくつかの利点があります。 –

+0

これはありません、このステップは、基本的に私は現在逐次行うように強制されているこのライブラリに数百の呼び出しです。コードは、基本的には、parallel.foreachに変えたいライブラリへの1回の呼び出しでforeachです。ライブラリへのすべての呼び出しが完了する前に機能的に行うことができます(次のステップのすべてのアイテムの戻り値のすべてが必要です) –

関連する問題