Multithreading WCF操作。上下文不是线程安全的吗?

Multithreading WCF操作。上下文不是线程安全的吗?,multithreading,wcf,thread-safety,wcf-extensions,Multithreading,Wcf,Thread Safety,Wcf Extensions,我正在检查WCF服务的代码。 在每条消息的头中,我们注入数据,服务稍后将使用这些数据来构建到DB的连接字符串。 这是因为服务将被多个不同的站点使用,每个站点都有自己的数据库,服务必须查询这些数据库。 我们使用wcf扩展性。我们有一个自定义MessageInspector,它在接收到请求后,从消息头提取数据,创建一个上下文(实现IExtension)并将其添加到OperationContext.Current.Extensions。 在发送回复之前,将从Extencions集合中删除自定义上下文

我正在检查WCF服务的代码。 在每条消息的头中,我们注入数据,服务稍后将使用这些数据来构建到DB的连接字符串。 这是因为服务将被多个不同的站点使用,每个站点都有自己的数据库,服务必须查询这些数据库。 我们使用wcf扩展性。我们有一个自定义MessageInspector,它在接收到请求后,从消息头提取数据,创建一个上下文(实现IExtension)并将其添加到OperationContext.Current.Extensions。 在发送回复之前,将从Extencions集合中删除自定义上下文

这是一种相当常见的模式,如下所述:

在这里:

只要服务接收请求、处理请求、发送回复并接收下一个请求,这一切都可以正常工作。 但是,如果服务收到一个请求,并且在能够答复之前,它收到了第二个请求,该怎么办?我构建了一个小型控制台应用程序来测试它。我从两个不同的线程发送了两条消息,我让wcf服务等待了2秒钟,以确保在第一个请求完成之前第二个请求到达,这就是我得到的:

站点Id:test1450;会话:uuid:2caf47cf-7d46-4d72-9275-d9c037fa0e70;id=2:螺纹id:6

站点Id:test1450;会话:uuid:2caf47cf-7d46-4d72-9275-d9c037fa0e70;id=3:螺纹id:22

看起来wcf在两个不同的线程上创建了两个会话,但站点Id是相同的。不应该。从这一点来看,OperationContext.Current.Extensions似乎是线程之间共享的集合。 现在我倾向于认为我的测试是错误的,我错过了一些东西


是否有人尝试过类似的操作并发现OperationContext.Current不是线程安全的?

OperationContext.Current与HttpContext.Current等其他类似属性一样具有线程仿射(或线程静态)值。因此,它们是线程安全的,因为多个线程可以读取它们,但不同的线程将获得不同的实例。它们可以被认为是特定线程和实例之间的字典

因此在这种情况下,它们不是线程安全的


请求由线程池提供服务,因此并发请求将具有不同的线程ID。(在线程池已满的情况下,请求将被搁置)

如果是这种情况,那么我仍然不理解为什么我会得到相同的站点Id。如果每个线程应该得到不同的数据,那么我假设它应该得到它正在处理的消息中包含的站点Id。看起来每个线程的当前操作上下文不同(不同的会话Id),但Extensions集合似乎仍然包含相同的自定义上下文实例。如果可能有帮助:我尝试以不同方式配置服务器:InstanceContextMode=InstanceContextMode.PerCall,ConcurrencyMode=ConcurrencyMode.single这是它最初的配置方式;InstanceContextMode=InstanceContextMode.PerSession,ConcurrencyMode=ConcurrencyMode.Multiple。但问题是相同的,当我说不同的数据时,我应该说不同的实例。根据配置的不同,某些属性可能具有相同的值,但实际实例绑定到线程。我们可以把这些属性看作是线程和对象的字典,每个线程都有自己的实例。如果您启动一个新线程并读取此属性,您将得到null,即使您希望实例绑定到实际的requestnote,但wcf会跟踪此情况,因此,如果服务在内部创建线程,这只是一个问题。服务的调用者不必担心并发性