我们有一个Web服务,它将请求发送到承载WCF服务进行处理的Windows服务。
界面很简单:
namespace MyApp
{
[ServiceContract]
public interface IMyApp
{
[OperationContract]
string DoSomething(string xml);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
class MyAppWcf : IMyApp
{
public string DoSomething(string xml)
{
Customer customer = GlobalObject.GetCustomer(xml); //millisecs
return customer.DoSomething(xml); //Takes 5-10 seconds
}
}
}
GlobalObject在WindowsService.OnStart()上实例化,包含客户对象所需的所有静态数据。 界面DoSomething()将被调用到ca. 30个不同的客户。
问题:
1.现在的默认线程行为是什么?每个电话都要等到最后一个电话完成吗?
2.改变InstanceContextMode会有什么影响?
REAL 问题:
最多有1000个客户对象,可以并行调用2个不同的客户对象,但同一个客户对象不能。例如
DoSomething(“客户1”); =>继续前进。 10秒内回答
DoSomething(“客户2”); =>与上述呼叫并行前进
DoSomething(“客户2”); =>将等待DoSomething的最后一次调用(“客户2”)完成
我的服务行为设置应该是什么?我是否必须实现锁定机制以防止同时处理同一个对象多次?
感谢。
编辑2:GlobalObject.GetCustomer()只是从字典中检索XML中提到的客户。
答案 0 :(得分:2)
行。我不确定在使用ConcurrencyMode
实例化时我是否知道PerCall
被忽略,但是查看我自己的项目,我使用PerCall
实例化并且没有为{{1}指定任何值}}。显然,我确实知道这一点,并且没有在我的代码中记录它。现在已经纠正了。
我的项目很像您描述的项目,我使用ConcurrencyMode
正如我已经提到的那样。这就是这意味着什么。
InstanceContextMode.PerCall
MyAppWcfInst.DoSomething( "<customer id=A/>" );
MyAppWcfInst.DoSomething( "<customer id=B/>" );
所有三个客户端将同时与您的WCF服务进行交互,但每个客户端都有自己的实例并在单独的线程中运行。因此,虽然每个客户端的每个调用都是单线程的,但它们可以同时处于活动状态。这意味着多个客户端可以同时访问Customer对象列表。
Client1和Client2可以并行运行,因为它们处理不同的Customer对象,但Client3需要等到Client2完成才能与CustomerB“做某事”。所有这些意味着您需要在每个Customer对象中同步访问。换句话说,MyAppWcfInst.DoSomething( "<customer id=B/>" );
方法中的逻辑需要具有同步锁定,以防止多个客户端同时在客户上运行。
Customer.DoSomething()
这是我的WCF服务的工作方式。希望这会有所帮助。
答案 1 :(得分:1)
使用PerCall,您将获得并行处理的服务请求,每个请求都在MyAppWcf类的不同实例上。如果没有可用于发送它们的免费.NET线程池线程,则请求只需等待较早的一个完成。 如果您将其更改为Single,则除非您将ConcurrencyMode设置为Multiple,否则将序列化请求。
您真正关心的是GobalObject方法的并发访问安全性如何:如果这不安全,则上述代码也不是。
与Customer.DoSomething方法类似,如果它触及任何共享数据(例如它自己调用GlobalObject)。
我不明白你的意思是“一次只能处理一个客户对象”。如果这确实是真的,那么无论如何你都需要避免并行执行。