3

我们的 WCF 服务引用的库之一使用 ThreadStatic 变量。服务方法在每次调用开始时设置它的值。我想知道这是否安全——换句话说,我们能否保证只有一个线程专门用于整个调用?或者是否有可能调用可以在一个工作线程上开始并在另一个工作线程上结束?还是可以将工作线程交换到不同的方法调用然后再返回?

我们使用 ConcurrencyMode.Single 和 InstanceContextMode.PerSession 的默认值。

编辑

到目前为止,我能找到的唯一信息是这篇博文,其中指出一个调用可以由多个线程处理:

http://blogs.microsoft.co.il/blogs/applisec/archive/2009/11/23/wcf-thread-affinity-and-synchronization.aspx

这人说的对吗?是否有来自 Microsoft 的任何明确信息?

4

4 回答 4

3

如果您不确定是否始终可以使用 CallContext 类: CallContext.LogicalSetData CallContext.LogicalGetData

虽然如果线程发生更改,ThreadStatic 将不起作用,但逻辑​​ CallContext 在 .NET 中传递,即使您将创建自己的新线程/任务。

于 2012-11-15T22:49:29.437 回答
2

您所说的可以在多个请求之间传递单个请求的现象称为“线程敏捷性”。

简短的回答是不,您不能保证给定的请求将由单个线程处理。

在此处查看已接受的答案:WCF 请求处理线程敏捷吗?

*这是由 IIS 托管的 WCF 的情况

于 2012-11-12T09:20:32.067 回答
0

我有保存问题。为了调查我开始负载测试并开始测试 GetRolesForUser:

public override bool IsUserInRole(string username, string roleName)
    {
        object stub = new object();
        bool res;
        lock(stub)
        {
            RoleProviderCount++;
            ThreadId = Thread.CurrentThread.ManagedThreadId;
            res = GetRolesForUser(username).Contains(roleName);
        }
        return res;
    }

这是我的日志:

Timestamp: 06.11.2012 13:55:03 Message:  ServiceCalls count 1; RoleProvider count 1 Thread Id 9 
Timestamp: 06.11.2012 14:00:22 Message:  ServiceCalls count 1; RoleProvider count 1 Thread Id 9 
Timestamp: 07.11.2012 5:30:38 Message:  ServiceCalls count 1; RoleProvider count 1 Thread Id 11 
Timestamp: 07.11.2012 5:31:58 Message:  ServiceCalls count 1; RoleProvider count 4 Thread Id 27 
Timestamp: 07.11.2012 5:31:58 Message:  ServiceCalls count 1; RoleProvider count 4 Thread Id 27 
Timestamp: 07.11.2012 5:31:58 Message:  ServiceCalls count 1; RoleProvider count 4 Thread Id 27 
Timestamp: 07.11.2012 5:31:58 Message:  ServiceCalls count 1; RoleProvider count 4 Thread Id 27 
Timestamp: 07.11.2012 5:31:58 Message:  ServiceCalls count 1; RoleProvider count 4 Thread Id 27 
Timestamp: 07.11.2012 5:31:58 Message:  ServiceCalls count 1; RoleProvider count 4 Thread Id 27 
Timestamp: 07.11.2012 5:31:59 Message:  ServiceCalls count 1; RoleProvider count 5 Thread Id 22 
Timestamp: 07.11.2012 5:31:59 Message:  ServiceCalls count 1; RoleProvider count 8 Thread Id 26 
Timestamp: 07.11.2012 5:31:59 Message:  ServiceCalls count 1; RoleProvider count 8 Thread Id 26 
Timestamp: 07.11.2012 5:32:00 Message:  ServiceCalls count 1; RoleProvider count 10 Thread Id 23 
Timestamp: 07.11.2012 5:32:00 Message:  ServiceCalls count 1; RoleProvider count 11 Thread Id 29 
Timestamp: 07.11.2012 5:32:00 Message:  ServiceCalls count 1; RoleProvider count 12 Thread Id 22 
Timestamp: 07.11.2012 5:32:00 Message:  ServiceCalls count 1; RoleProvider count 13 Thread Id 27 
Timestamp: 07.11.2012 5:32:00 Message:  ServiceCalls count 1; RoleProvider count 14 Thread Id 24 
Timestamp: 07.11.2012 5:32:00 Message:  ServiceCalls count 1; RoleProvider count 15 Thread Id 30 
Timestamp: 07.11.2012 5:32:00 Message:  ServiceCalls count 1; RoleProvider count 16 Thread Id 26 
Timestamp: 07.11.2012 5:32:01 Message:  ServiceCalls count 1; RoleProvider count 17 Thread Id 11
Timestamp: 07.11.2012 5:32:01 Message:  ServiceCalls count 1; RoleProvider count 18 Thread Id 23
Timestamp: 07.11.2012 5:32:01 Message:  ServiceCalls count 1; RoleProvider count 20 Thread Id 26
Timestamp: 07.11.2012 5:32:01 Message:  ServiceCalls count 1; RoleProvider count 20 Thread Id 26
Timestamp: 07.11.2012 5:32:01 Message:  ServiceCalls count 1; RoleProvider count 21 Thread Id 24

因此,RoleProvider 方法是从同一个线程调用的。(WCF服务配置实例方式PerCall,并发Multiple)

于 2012-11-07T06:10:28.700 回答
0

以下是我一位同事的回复:


你提到的“这个人”一定是错的。在实际服务方法的执行过程中,无法更改线程。这适用于任何方法,并且与 WCF 无关。

可以创建一个异步调用,然后在另一个方法/线程上完成;但这没什么特别的: http: //tao.qshine.com/note/ThreadIssue.html

我当然很想知道这个线程敏捷性是否真的与方法调用切换线程有关……我们在这里谈论的是托管线程,微软没有理由更改线程 ID。CallContext 是 Microsoft 提供的一项功能,以便您在执行异步调用时可以存储状态。

实例上下文可能使用不同的线程来实例化服务而不是执行方法——尽管如果您使用 PerCall,这不会发生。你真的在使用会话吗?如果不是,您应该切换到 PerCall。同一会话中的不同调用可能会使用不同的线程。


似乎有道理。任何意见?

于 2012-11-14T05:59:35.343 回答