WCF是否会破坏lock关键字?

时间:2011-07-18 17:28:11

标签: c# .net

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

它给出了以下示例,它似乎表明WCF完全破坏了C#中的lock关键字:

public class MyService : IContract
{
    //author of article originally did not initialize this in his illustration
    //initializing it here so that we can avoid talking about side issues.
    public static object wait_handle = new object();

    public int LongOperation()
    {
        lock (wait_handle)
        {
            Before(); //Thread1 has the lock

            LongWait(); //Threads might be switched here

            After(); // Thread2 does not have the lock but
                        it runs.
            return 0;
        }           
    }


    public int SecondOperation()
    {
        // If accidently Thread1 is allocated it has the handle and would enter the lock.
        lock (wait_handle)
        {
            DoWork();
        }

        return 0;
    }
}

这似乎对微软来说是一个可怕的决定,因为它打破了关键字的常见用法,并且意味着我无法可靠地使用WCF服务中任何以前开发的代码库,除非我验证他们不在代码中使用“锁定”。 (我认为如果文章为真,这意味着lock关键字使用某种线程本地类型存储)。

微软真的这样做了吗?或者我错过了什么?或者参考文章是否不准确?

3 个答案:

答案 0 :(得分:5)

我认为该文章的作者误解了WCF服务中缺少线程亲和力的含义。 MSDN摘录自Programming WCF Services一书,专门介绍并发性,值得一读。

简短的回答似乎是,在多调用并发模型中,您无法确定您在服务中使用的线程是否具有您正在寻找的所需关联(例如,如果您的线程需要使用线程本地存储或者它在UI线程上运行。您可以通过使用SynchronizationContext专门设置此项,但是一旦输入服务,该调用的线程关联就会被锁定。

  

传入服务调用在I / O完成线程池的工作线程上执行,与任何服务或资源线程无关。这意味着默认情况下,服务不能依赖任何类型的线程关联(即,始终由同一线程访问)。同样,服务默认不依赖于在主机或服务开发人员创建的任何主机端自定义线程上执行。

没有理由WCF下的一个线程可以随意停止它正在做的事情,整理它当前正在做的所有事情,并且可以访问并开始一个具有相同上下文的新线程。调用。这将是非常危险的,并且很难提供作者声称提供的那种可扩展性。 Monitor.Enter()和lock语句完全可以在WCF服务中使用,前提是您的代码需要该级别的同步。

答案 1 :(得分:2)

确保锁定实例,而不仅仅是null

public static readonly object wait_handle = new object();

答案 2 :(得分:2)

看起来你错过了一些非常重要的东西:WCF可能会也可能不会在同一个过程中执行。如果WCF在单个进程中运行并锁定静态对象,则将具有有效锁定。

另一方面,如果WCF 在单个进程中运行(例如,IIS托管可能会导致这种情况),那么您的锁将毫无价值,因为一个进程会锁定,但另一个过程不会。

WCF服务于一个非常特定的目的:客户端 - 服务器通信。嗯,还有一点比这更多,但绝大多数WCF编程都是针对SOAP或RESTful Web服务的。编程此类服务时,避免锁定几乎总是一个好主意,因为服务可能一次只能处理多个请求,而锁定会导致其他请求暂停(这可能会导致超时)。

如果您使用的是需要串行访问的资源,请查找单个服务调用的替代解决方案。