2010-11-18 46 views
3

我们有一个Web服务,它将请求发送到托管WCF服务进行处理的Windows服务。Windows服务/ WCF和线程,初学者问题

界面简单:

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()将被调用到约。 30个不同的客户。

问题:
1.什么是现在的默认线程行为?每次通话都必须等到最后一次通话完成?
2.什么影响会改变InstanceContextMode?

REAL问题:
有多达1000个客户对象,2个不同的客户对象可以被称为并行,但同样缺一不可。例如
DoSomething(“Customer 1”); =>继续。在10秒内回答
DoSomething(“Customer 2”); =>与上述呼叫同时进行。
DoSomething(“Customer 2”); =>将等待DoSomething(“客户2”)的最后一次呼叫完成

我的服务行为设置应该如何,我必须实现锁定机制以防止同时处理多个并行对象?

谢谢。

编辑2:GlobalObject.GetCustomer()只是从字典中检索XML中提到的客户。

回答

2

好的。我不确定我知道ConcurrencyMode在使用PerCall实例化时被忽略,但是看看我自己的项目,我使用PerCall实例化,并且没有为ConcurrencyMode指定任何值。显然,我确实知道这一点,只是没有在我的代码中记录它。现在纠正了。

我的项目与您描述的很相似,我使用InstanceContextMode.PerCall,因为我已经提到过。这就是这个意思。

  • 客户端1 =>MyAppWcfInst.DoSomething("<customer id=A/>");
  • 客户端2 =>MyAppWcfInst.DoSomething("<customer id=B/>");
  • Client3 =>MyAppWcfInst.DoSomething("<customer id=B/>");

所有这三个客户端将同时与WCF服务交互,但他们每个人都会有自己的实例并在一个单独的线程内运行。因此,虽然每个客户端的每个呼叫都是单线程的,但它们可以同时处于活动状态。这意味着客户对象列表可以被多个客户同时访问。

客户端1和客户端2可以并行操作,因为它们处理不同的客户对象,但客户端3需要等到客户端2完成后才能够与客户端“做些什么”。所有这一切意味着您需要在每个Customer对象中同步访问。换句话说,Customer.DoSomething()方法中的逻辑需要有一个同步锁定,以防止多个客户端同时在客户端操作。

class Customer 
{ 
    private object _sync = new object(); 

    public string DoSomething(string xml) 
    { 
     lock (_sync) 
     { 
      // put your logic here... 
     } 
    } 
} 

这是我的WCF服务的工作方式。希望这可以帮助。

+0

感谢马特,那看起来正是我所需要的。 – 2010-11-19 21:27:05

1

使用PerCall,您将获得对并行处理的服务的请求,每个服务都在MyAppWcf类的不同实例上。如果没有可用的免费.NET线程池线程来分派它们,请求将只需等待较早的一个完成。 如果将其更改为Single,那么请求将被序列化,除非将ConcurrencyMode设置为Multiple。

你真正的担心应该是如何安全的并发访问GobalObject方法是:如果这不是安全的,上面的代码也不是。

与Customer.DoSomething方法类似,如果它触及任何共享数据(如本身调用GlobalObject)。

我不明白你的意思是“一次只能处理一个客户对象”。如果这是真的,那么你需要避免平行执行。

+0

可能有1000个客户对象。每个客户对象本身都是线程安全的,但同一个客户对象不能同时运行。例如客户1和客户2可以并行处理。 GlobalObject.GetCustomer是安全的(只读)。 – 2010-11-18 16:38:46

+1

Re Matt Davis的回答......我一直都明白,当InstanceContextMode是PerCall时,ConcurrencyMode被忽略,这就是MSDN文档所说的。所以我认为你已经有了并行执行的功能......但我会检查一下,以防文档错误。 – 2010-11-18 18:40:17

+0

+1 @Chris Dickson。我根据这些信息更新了我的回复,显然我一直在这个方面忘了。谢谢。 – 2010-11-19 03:11:36