簡體   English   中英

在C#中確保靜態方法的線程安全

[英]Ensuring Thread-Safety On Static Methods In C#

我有一些我目前在靜態類/方法中的代碼,但我想檢查它是否是線程安全的。 從我讀過的內容來看,我認為這應該沒問題,但我腦子里的一些事情卻說它可能不是。 我的網頁的數據處理階段使用外部Web服務來創建訂單記錄,這可能非常慢:可能是30-40秒,可能是5或10分鍾(這不在我的手中)所以我要開火返回頁面返回給用戶,然后啟動一個新線程,然后在處理完成后通過電子郵件發送給用戶。 這是一個靜態類/方法。 如果我的所有對象都是在特定方法中創建的(除了系統默認值,這是常見的)該方法應該是線程安全的,不應該。 所以,例如,如果我有

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(....)階段)並發線程? 我明白,如果我開始使用類成員然后在方法中使用它們,這肯定會引入不同線程覆蓋值的問題,但只要在方法中創建對象,它們應該沒問題,應該'他們?

它看起來不像你在那里訪問任何共享數據; 您正在請求遠程資源,並在每次執行此方法時構建一組唯一的數據。 那里不需要同步。

這里方法的每次執行都是創建局部變量 - 它是自己的副本。 所以什么都沒有被分享。

如果靜態方法不訪問任何靜態(類)數據,則它應該是線程安全的。 唯一可能的爭用點是它可能使用的外部資源(例如文件或其他系統資源),以及傳入的數據。只有您知道這種用法的上下文。

可能在爭用中的事物的使用可以用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 ;
   }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM