对WCF通道的线程安全访问

时间:2014-01-10 15:07:44

标签: asp.net wcf web-services thread-safety authorize.net

我有一个ASP.NET应用程序,它使用第三方/异地支付处理器的“服务引用”。 我从支付处理器下载的示例代码包括以下内容:

   public class SoapAPIUtilities{

      private static CustomerProfileWS.Service service = null;

      public static CustomerProfileWS.Service Service{
         get{
            if(service == null){
               service = new CustomerProfileWS.Service();
            }
            return service;
         }
      }   
   }

我生成CustomerProfileWS.Service automatically using Visual Web Developer:它的自动生成的实现是ServiceModel.ClientBase的子类的子类, MSDN文档为“任何实例成员都不保证是线程安全的”。

要从ASP.NET页面使用此服务,我想我需要访问服务线程安全,以上不是?

如果它不是线程安全的,那么什么是使其成为线程安全的更好方法:

  • 包装一个在静态单例(e.g. as shown here)周围实现锁定的访问器类?
  • 不要使用静态单身人士;而是根据需要创建多个/临时CustomerProfileWS.Service实例,作为需要它们的ASP.NET页面的方法中的局部变量?

3 个答案:

答案 0 :(得分:1)

使代理线程安全且单例不适合Web应用程序。

当另一个线程正在使用它时,代理通道可能会出现故障。此外,您不希望为每个操作锁定通道,因为网站同时有多个请求,并且它们将在行中处理,等待长时间运行的任务,如调用Web服务。

您需要为每个ASP .NET请求创建一个新的代理通道。这是一项昂贵的操作,因此您可能希望查看本文以确保创建昂贵的部分得到缓存:

Performance Improvement for WCF Client Proxy Creation

另一种方法是创建一个代理池,这样您就不必每次都创建一个新代理,但如果可用,则重用现有代理。可以在这里找到一个例子:

A Sample for WCF Client Proxy Pooling

答案 1 :(得分:0)

我会选择你建议的第二个选项......

  

不要使用静态单身人士;而是创建多个/临时   CustomerProfileWS.Service实例根据需要,作为局部变量   需要它们的ASP.NET页面的方法?

答案 2 :(得分:0)

我将其更改为private static readonly CustomerProfileWS.Service service = new CustomerProfileWS.Service();

这将以线程安全的方式创建您的单例。

但是,如果多个线程访问WCF代理,则可以关闭连接,而另一个是中间操作。

我认为每个ASP.NET请求的代理可能更适合这里。