2012-09-12 16 views
5

現在、静的なクラス/メソッドのコードがありますが、スレッドセーフであることを確認したいと考えました。私が読んだことから、これは大丈夫だと思いますが、私の心の裏側にあるものはそうでないかもしれないと言っています。私のWebページのデータ処理段階では、外部Webサービスを使用して注文記録を作成していますが、これはかなり遅くなる可能性があります:30〜40秒、おそらく5〜10分(これは手の届かない部分です)ユーザーに戻るページを返し、処理が完了したら新しいスレッドを開始してユーザーに電子メールを送信します。これは現在、静的なクラス/メソッドです。すべてのオブジェクトが特定のメソッド内で作成されている場合(システムのデフォルト値以外は共通)、そのメソッドはスレッドセーフでなければなりません。ですから、例えば、私はスタティックメソッドのスレッドセーフティの確保C#

public static class ProcessOrder() 
{ 
    public static int GetOrderMaxSize() 
    { 
     return (....gets and parses ConfigurationManager.AppSettings["MaxOrderSize"]...); 
    } 

    public static bool CreateOrder(Order order) 
    { 
     XmlDocument xmlDoc = GetOrderXML(order); 
     bool check = false; 
     using (CreateOrderXML.Create xmlCo = new CreateOrderXML.Create()) 
     { 
      xmlCo.Timeout = 60000; 
      System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding(); 

      string xmlString = ""; 
      using (StringWriter stringWriter = new StringWriter()) 
      { 
       using (XmlWriter xmlWriter = XmlWriter.Create(stringWriter)) 
       { 
        xmlDoc.WriteTo(xmlWriter); 
        xmlWriter.Flush(); 
        xmlString = stringWriter.GetStringBuilder().ToString(); 
       } 
      } 

      byte[] bXMLOrder = encoding.GetBytes(xmlString); 
      byte[] breturnMessage; 

      check = xmlCo.Create(bXMLOrder, out breturnMessage); 
      .... do something with return message 
     } 
     return check; 
    } 

    private static XmlDocument GetOrderXML(Order order) 
    { 
     ... creates an XML object for the order 
    } 
} 

を持っていた場合(CreateOrderXMLは、WebサービスのURL /メソッドへのサービスの参照である)ことが、特に長時間実行のために、スレッドセーフになります(主にxmlCo.Createで( ....)ステージ)並行スレッド?私がクラスメンバーを入れ始めた後、メソッドで使用した場合、異なるスレッドが値を上書きするという問題が発生することは間違いありませんが、メソッド内でオブジェクトが作成されていれば、彼ら?

答えて

12

共有データにアクセスしているようではありません。リモートリソースを要求しており、このメソッドを実行するたびに固有のデータセットを構築しています。そこに同期する必要はありません。

ここでメソッドを実行すると、ローカル変数が作成されます。これは独自のコピーです。だから何も共有されていません。

+0

はい、私は意図的にクラス全体で「システム全体のデフォルト」変数を使用していました。メソッドのパラメータを使用してユーザー/セッションを開始します。しかし、私はまだ頭の後ろに警報ブザーが鳴っていた、うまくいけば彼らはちょうど "健康なパラノイア"です。 –

+0

私には健康的なパラノイアのような音がする! –

5

静的メソッドが静的(クラス)データにアクセスしない場合は、スレッドセーフである必要があります。競合の唯一の可能な点は、使用する外部リソース(ファイルやその他のシステムリソースなど)、および渡されるデータです。そのような用途のコンテキストを知っているだけです。

競合している可能性のあるものの使用は、lockまたは他の原型とシリアル化することができます。デッドロックしないように、同じ順序でリソースをシリアライズすることを忘れないでください。

lock(latch_a) 
{ 
    process(object_a) ; 
    lock (latch_b) 
    { 
    process(object_a,object_b) ; 
    } 
} 

と逆行い、別の方法:あなたが一つのリソースAとBを使用する方法がある場合は、あなたの2つのスレッドがデッドロックになるいくつかの時点で、

lock(latch_b) 
{ 
    process(object_b) ; 
    lock (latch_a) 
    { 
    process(object_a,object_b) ; 
    } 
} 

をそれらのそれぞれがリソースを必要とするときもう1つは、前記リソースへのアクセスを放棄することができるためである。

注: lockステートメントの詳細については、C#のドキュメントを参照してください。一般に、ロックされたオブジェクトは、シリアライズされている共有リソースアクセスを表します(そしてそうかもしれません)。一般的なパターンは次のようなものです:

class Widget 
{ 
    private static readonly object X = new object() ; 

    public void Foo() 
    { 
    lock(X) 
    { 
     // Do work using shared resource 
    } 
    return ; 
    } 

} 
+0

lat_aとlatch_bオブジェクトは一度作成して静的メソッドの各呼び出しに渡す必要がありますか? – Doug

+0

@Doug:私の修正された答えを見てください。 –

関連する問題