【问题标题】:ThreadStatic - Does a WCF method call execute exclusively on a single thread?ThreadStatic - WCF 方法调用是否仅在单个线程上执行?
【发布时间】:2012-11-07 04:05:29
【问题描述】:

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

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

编辑

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

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

这个人说的对吗?有没有来自微软的确切信息?

【问题讨论】:

标签: wcf threadstatic


【解决方案1】:

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

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

【讨论】:

  • 这太棒了 - 从来不知道那个。
  • 我没有意识到重构是一种选择。如果您可以选择重写使用 ThreadStatic 的代码,为什么不正确地使用 OperationContext 呢?如果您需要与消息检查员一起做事,那么CallContext is not suitable either
【解决方案2】:

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

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

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

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

【讨论】:

  • 我希望你是对的,但为了赏金,我正在寻找明确说明这一点的官方 WCF 文档。你知道吗?
【解决方案3】:

这是我一位同事的回复:


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

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

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

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


似乎有道理。有cmets吗?

【讨论】:

    【解决方案4】:

    我有保存问题。 调查我开始负载测试并开始测试 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)

    【讨论】:

    • 也许答案在并发多重的实现中?也许这篇文章可以帮助你codeproject.com/Articles/89858/…
    • 你的回答让我很困惑。您能否添加更多解释和/或更多代码来显示您的日志文件如何回答问题?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-18
    相关资源
    最近更新 更多