我有一个ASP.Net站点,它使用ASP.Net XML webservices。为了与webservice中的每个web方法进行通信,我有一个带有静态业务方法的静态类,一个用于webservice中的每个web方法。静态业务方法每次调用时都会创建webreference类的新实例。 webreference类的新实例仅用于调用webmethod,webreference实例中的所有属性都不会从其默认值更改。
我的问题是,我是否可以创建webreference类的全局静态实例,以供所有静态业务方法使用,而不是每次调用静态业务方法时都创建新的静态业务方法? (基本上是webreference类线程安全的实例?)
我担心的是webreference类的实例有一些不是线程安全的属性,因为代码是针对网站的,多个线程同时调用相同的静态业务方法会导致线程之间出现问题
我问的原因是尝试找到我可以做的其他更改来提高网站的性能。在跟踪网站的性能时,我发现花费了大量时间来创建webreference类的实例。此外,基于垃圾收集计数器,我看到很多时间也在那里度过。
示例代码:
这就是我目前正在做的事情
public static class WebMethodWrapper
{
public static bool CallMethodA(string p1)
{
using(com.mysite.service1 _provider = new com.mysite.service1())
{
return(_provider.WebMethodA(p1));
}
}
public static bool CallMethodB(string p1)
{
using(com.mysite.service1 _provider = new com.mysite.service1())
{
return(_provider.WebMethodB(p1));
}
}
}
这就是我想做的事情
public static class WebMethodWrapper
{
static com.mysite.service1 _Provider = null;
static WebMethodWrapper()
{
_Provider = new com.mysite.service1();
}
public static bool CallMethodA(string p1)
{
return(_Provider.WebMethodA(p1));
}
public static bool CallMethodB(string p1)
{
return(_Provider.WebMethodB(p1));
}
}
答案 0 :(得分:1)
我的问题是,我是否可以创建webreference类的全局静态实例,以供所有静态业务方法使用,而不是每次调用静态业务方法时都创建新的静态业务方法? (基本上是webreference类线程安全的实例?)
我担心的是webreference类的实例有一些不是线程安全的属性,因为代码是针对网站的,多个线程同时调用相同的静态业务方法会导致线程之间出现问题
一个快乐的好问题,你似乎在回答的路上很好。我同意您可能会坚持使用您当前的方法,其中每个静态方法都会创建自己的服务客户端本地副本。这不仅从客户端的角度鼓励线程安全,而且还保证使用唯一代理完成对服务的远程调用 - 其中结果不可能与其他请求多路复用。 / p>
如果您使用共享实例的其他路径,那么您必须考虑服务在一个线程中出错的情况。
然后,您需要使该客户端无效,重新创建一个新客户端。所有这些都需要安全线程锁定。管理这个业务流程有点非常复杂。
让我们考虑您的替代代码:
public static bool CallMethodA(string p1)
{
return(_Provider.WebMethodA(p1));
}
让我们说这是第一次成功召集。现在想象你需要在5秒钟之后调用这5分钟,但遗憾的是此时服务器已断开连接,因为它超时 5分钟。您的第二次电话错误。需要调整上述代码以允许这些场景。在下面的简单示例中,我们在失败期间重新创建客户端并再次尝试。
也许:
public static class WebMethodWrapper
{
static com.mysite.service1 _Provider = null;
static object _locker = new object();
static WebMethodWrapper()
{
_Provider = new com.mysite.service1();
}
static com.mysite.service1 Client
{
get
{
lock (_locker)
{
return _Provider;
}
}
}
public static bool CallMethodA(string p1)
{
try
{
return (Client.WebMethodA(p1));
}
catch (Exception ex) // normally just catch the exceptions of interest
{
// Excercise for reader - use a single method instead of repeating the below
// recreate
var c = RecreateProxy();
// try once more.
return (c.WebMethodA(p1));
}
}
public static bool CallMethodB(string p1)
{
try
{
return (Client.WebMethodB(p1));
}
catch (Exception ex) // normally just catch the exceptions of interest
{
// Excercise for reader - use a single method instead of repeating the below
// recreate
var c = RecreateProxy();
// try once more.
return (c.WebMethodB(p1));
}
}
static com.mysite.service1 RecreateProxy()
{
lock (_locker)
{
_Provider = new com.mysite.service1();
return _Provider;
}
}
}
所有这些都可以包含在一些通用服务客户端缓存中,这些缓存可以维护连接池中的现成客户端集合吗?也许后台线程定期ping每个客户端让它们保持活着?也许是读者的练习。
然后,从服务的角度来看,在线程之间共享相同的代理实例可能不是一个好主意,除非您的服务标记为 per-call ,这可能会影响您的设计,也可能不会影响您的设计或表现。
您当前的代码可以说更安全,更简单。
祝你好运!