ThreadStatic - WCF方法调用是否在单个线程上执行?

时间:2012-11-07 04:05:29

标签: wcf threadstatic

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

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

修改

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

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

这家伙是对的吗?是否有来自Microsoft的确切信息?

4 个答案:

答案 0 :(得分:3)

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

如果线程确实发生了变化,ThreadStatic将无法工作,而Logical CallContext将在.NET中传递,即使您要创建自己的新线程/任务。

答案 1 :(得分:2)

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

简短的回答是,不,你不能保证一个线程处理一个给定的请求。

请在此处查看已接受的答案:Are WCF request handling Thread Agile?

*这是由IIS承载的WCF的情况

答案 2 :(得分: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,并发多个)

答案 3 :(得分:0)

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


  

你提到的“这个人”必须是错的。没有办法了   线程要在实际执行的中间进行更改   服务方式。任何方法都是如此,与WCF无关。

     

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

     

我当然非常   有兴趣听听这个线程敏捷性事实是否真的与之相关   方法调用切换线程...我们正在讨论托管线程   在这里,微软没有理由改变线程ID。   CallContext是Microsoft提供的一项功能,您可以这样做   如果您执行异步调用,则存储状态。

     

有可能   实例上下文使用不同的线程来实例化   服务比执行方法 - 但如果您使用PerCall这将   不会发生。你真的在使用会话吗?如果没有,你应该切换   到PerCall。可能在同一个内部进行不同的调用   会话将使用不同的线程。


似乎有道理。有什么意见吗?