Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C中确保静态方法的线程安全#_C#_.net_Multithreading_Static_Thread Safety - Fatal编程技术网

C# 在C中确保静态方法的线程安全#

C# 在C中确保静态方法的线程安全#,c#,.net,multithreading,static,thread-safety,C#,.net,Multithreading,Static,Thread Safety,我在静态类/方法中有一些代码,但我想检查它是否是线程安全的。从我所读到的,我认为这应该是好的,但在我的脑海里的东西是说,它可能不是。我的网页的数据处理阶段使用外部web服务创建订单记录,这可能非常慢:可能30-40秒,可能5或10分钟(这是我无法控制的),因此我打算向用户发送一个返回页,然后启动一个新线程,然后在处理完成后向用户发送电子邮件。这当前在一个静态类/方法中。如果我的所有对象都是在特定方法中创建的(除了系统默认值,这是常见的),那么该方法应该是线程安全的,不是吗。比如说,如果我 pub

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

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


这里方法的每次执行都是创建局部变量——它自己的副本。因此,任何东西都不会被共享。

如果您的静态方法不访问任何静态(类)数据,那么它应该是线程安全的。唯一可能的争用点是它可能使用的外部资源(例如,文件或其他系统资源)和传入的数据。只有你知道这种用法的上下文

类似于可能存在争用的东西的使用可以用e
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) ;
   }
}
在某个时刻,当两个线程中的每一个都需要一个资源,而另一个线程需要一个资源,然后才能放弃对该资源的访问时,这两个线程就会死锁

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

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

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

}

是的,我特意在类本身中只使用了“系统范围的默认”变量,并且我通过方法的参数将处理可能特定于用户/会话所需的所有内容传入。但我的后脑勺里仍然有警报蜂鸣器响起,希望它们只是“健康的偏执狂”。听起来像是健康的偏执狂!是否需要创建一次闩锁a和闩锁b对象,然后将其传递给对静态方法的每次调用?@Doug:请参阅我的修订答案。