17

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

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

在哪里存储当前 WCF 调用的数据?ThreadStatic 安全吗?

和这里:

http://social.msdn.microsoft.com/Forums/vstudio/en-US/319cac66-66e8-4dfe-9a82-dfd289c9df1f/wcf-doesnt-have-session-storage-so-where-should-one-store-呼叫特定数据?forum=wcf

只要服务接收到请求,处理它,发送回复并接收下一个请求,这一切都可以正常工作。但是,如果服务收到一个请求并且在能够回复之前收到第二个请求怎么办?我构建了一个小型控制台应用程序来测试它。我从 2 个不同的线程发送 2 条消息,我让 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 创建了在 2 个不同线程上执行的 2 个会话,但站点 ID 是相同的。它不应该。由此看来,OperationContext.Current.Extensions 是线程之间共享的集合。现在我倾向于认为我的测试是错误的,我错过了一些东西。

有没有人尝试过类似的事情并发现 OperationContext.Current 不是线程安全的?

4

1 回答 1

12

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

所以在这种情况下,它们不是线程安全的。

请求由线程池提供服务,因此并发请求将具有不同的线程 ID。(直到线程池已满,然后请求将被搁置)

于 2013-10-10T09:42:13.507 回答