我有一个使用 ASP.Net XML 网络服务的 ASP.Net 站点。为了与 web 服务中的每个 web 方法通信,我有一个静态类和静态业务方法,一个用于 web 服务中的每个 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));
}
}
最佳答案
My question is can I create just a global static instance of the webreference class to use by all of the static business methods instead of creating a new one each time a static business method is called? (Basically are instances of a webreference class thread safe?)
My concern here is that the instance of the webreference class has some properties that are not thread safe and since the code is for a web site, multiple threads calling the same static business methods at the same time would cause issues between the threads.
一个很好的问题,您似乎已经准备好回答了。我同意您应该可能坚持您当前的方法,其中每个静态方法都创建自己的服务客户端本地副本。这不仅从客户端的角度鼓励了线程安全,而且还保证了对服务的远程调用是使用唯一代理完成的 - 结果不会与其他请求复用。
如果您使用共享实例的另一条路线,那么您必须考虑服务在一个线程中出现故障的情况。
- 也许超时了?
- 也许某些远程业务逻辑失败了?
- 可能网络出现故障是因为您的室友正在下载最新一集权力的游戏,超出了您的下载配额?
然后您需要使该客户端失效并重新创建一个新客户端。所有这些都需要安全线程锁定。管理这种编排变得相当复杂。
让我们考虑您的替代代码:
public static bool CallMethodA(string p1)
{
return(_Provider.WebMethodA(p1));
}
假设这是第一次成功调用。现在假设您需要在 5 分 5 秒后调用它,但不幸的是此时服务器已经切断了连接,因为它的超时为 5 分钟。你的第二个电话 faults。需要调整上述代码以允许这些情况。在下面的简单示例中,我们在失败期间重新创建客户端并再次尝试。
也许:
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,这可能会也可能不会影响您的设计或性能。
结论
您当前的代码可以说更安全、更简单。
祝你好运!
关于c# - 在 ASP.Net 中静态或作为单例使用 XML Webservices,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32517607/