2012-09-12 89 views
5

我有一些代碼,我目前有一個靜態類/方法,但我想檢查它是線程安全的。從我讀過的內容來看,我認爲這應該沒問題,但我腦海中的某些事情卻說它可能不是。我的網頁的數據處理階段使用外部網絡服務來創建訂單記錄,這可能很慢:可能需要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或其他主要事項序列化。不要忘記以相同的順序序列化資源,避免死鎖。如果您有使用資源A和B的一個方法:

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

,另一個做逆方法:

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

在某些時候,你的兩個線程死鎖,當他們每個人都需要的資源另一個需要bofore它可以放棄訪問所述資源。

編輯要注意: 請參閱lock陳述有關詳細信息,C#文檔。一般來說,鎖定的對象表示(並可能)正在對其進行序列化的共享資源訪問。一個常見的模式是做這樣的事情:

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

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

} 
+0

是否需要創建一次latch_a和latch_b對象,然後傳遞給靜態方法的每個調用? – Doug

+0

@Doug:看到我修正的答案。 –