5

我目前在静态类/方法中有一些代码,但我想检查它是否是线程安全的。从我读过的内容来看,我认为这应该没问题,但在我的脑海里有些东西说它可能不是。我的网页的数据处理阶段使用外部 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(....) 阶段)并发线程?我知道如果我开始放入类成员然后在方法中使用它们,这肯定会引入不同线程覆盖值的问题,但只要在方法中创建对象,它们应该没问题,不应该他们吗?

4

2 回答 2

13

您似乎没有访问那里的任何共享数据;您正在请求远程资源,并在每次执行此方法时构建一组唯一的数据。那里不需要同步。

此处方法的每次执行都在创建局部变量 - 它是自己的副本。所以没有任何东西被共享。

于 2012-09-12T16:29:35.173 回答
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) ;
   }
}

在某些时候,你的两个线程会死锁,当它们中的每一个都需要一个资源时,另一个需要它才能放弃对所述资源的访问。

编辑说明:有关详细信息 ,请参阅该lock语句的 C# 文档。通常,锁定对象代表(并且可能是)正在序列化的共享资源访问。一种常见的模式是执行以下操作:

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

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

}
于 2012-09-12T16:48:07.783 回答