条件变量C#/。NET [英] Condition Variables C#/.NET

查看:1255
本文介绍了条件变量C#/。NET的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的追求建立一个条件变量类我偶然在做这件事,我想和堆栈溢出社区共享这一个平凡简单的方法。我在Google上搜寻了一​​个小时的大部分时间,并无法真正找到一个很好的教程或.NET十岁上下的例子,觉得不对,希望这能使用到其他人在那里了。

In my quest to build a condition variable class I stumbled on a trivially simple way of doing it and I'd like to share this with the stack overflow community. I was googling for the better part of an hour and was unable to actually find a good tutorial or .NET-ish example that felt right, hopefully this can be of use to other people out there.

推荐答案

这其实非常简单,一旦你知道锁的语义显示器

It's actually incredibly simple, once you know about the semantics of lock and Monitor.

但首先,你需要一个对象引用。您可以使用(但是要记住不是,这是公开,在这个意义上,只要有关于你的类可以锁定该引用如果你不舒服,你可以创建一个新的专用的参考,像这样的:

But first, you do need an object reference. You can use this (but remember than this is public, in the sense that anyone with a reference to your class can lock on that reference. If you are uncomfortable with this, you can create a new private reference, like this:

readonly object syncPrimitive = new object(); // this is legal

在某处的code,你想成为能够提供通知,就可以完成这样的:

Somewhere in your code where you'd like to be able to provide notifications, it can be accomplished like this:

void Notify()
{
    lock (syncPrimitive)
    {
        Monitor.Pulse(syncPrimitive);
    }
}

和在那里你会做实际工作的地方是一个简单的循环结构,像这样的:

And the place where you'd do the actual work is a simple looping construct, like this:

void RunLoop()
{
    lock (syncPrimitive)
    {
        for (;;)
        {
            // do work here...
            Monitor.Wait(syncPrimitive);
        }
    }
}

从外面看,这会看起来非常死锁十岁上下,但对于显示器当您的通话将解除锁定 Monitor.Wait锁定协议,其实,这是你已经获得了锁的要求,然后再调用其中 Monitor.Pulse Monitor.PulseAll Monitor.Wait

From the outside, this would look incredibly deadlock-ish but the locking protocol for the Monitor will release the lock when you call Monitor.Wait, actually, it's a requirement that you have obtained the lock before you call either Monitor.Pulse, Monitor.PulseAll or Monitor.Wait.

有一点需要注意,这种方法,你应该知道的。由于需要锁定举行调用显示器的通信方法之前你真的应该只挂在了锁的时间尽可能短。的一个变体的 RunLoop 这是对长时间运行的后台任务更友好的是这样的:

There's one caveat with this approach that you should know about. Since the lock is required to be held before calling the communication methods of Monitor you should really only hang on to the lock for an as short duration as possible. A variation of the RunLoop that is more friendly towards long running background tasks would look like this:

void RunLoop()
{

    for (;;)
    {
        // do work here...

        lock (syncPrimitive)
        {
            Monitor.Wait(syncPrimitive);
        }
    }
}

但现在我们改变了这个问题一点,因为锁,不再是用来保护共享资源,因此,如果您code即做的工作在这里.. 需要访问你需要一个额外的锁共享资源,保护该资源。

But now we've changed up the problem a bit, because the lock, is no longer used to protect the shared resource, so, if you code that is do work here... needs to access a shared resource you need a additional lock, protecting that resource.

我们可以利用上面的code创建一个简单的线程安全的生产国的消费集,但.NET已经提供了一个极好的 ConcurrentQueue< T> 的实施,这只是为了说明使用的简便性显示器是这样的。

We can leverage the above code to create a simple thread-safe producer consumer collection, although .NET already provides an excellent ConcurrentQueue<T> implementation, this is just to illustrate the simplicity of using Monitor like this.

class BlockingQueue<T>
{
    // We base our queue, on the non-thread safe 
    // .NET 2.0 queue collection
    readonly Queue<T> q = new Queue<T>();

    public void Enqueue(T item)
    {
        lock (q)
        {
            q.Enqueue(item);
            System.Threading.Monitor.Pulse(q);
        }
    }

    public T Dequeue()
    {
        lock (q)
        {
            for (; ; )
            {
                if (q.Count > 0)
                {
                    return q.Dequeue();
                }
                System.Threading.Monitor.Wait(q);
            }
        }
    }
}

现在这里的关键不是要建立一个拦截收集,也可以在.NET框架(见BlockingCollection)。问题的关键是要说明它是多么容易建立使用显示器类.NET来实现条件变量的事件驱动信息系统。希望对您有所助益。

Now the point here is not to build a blocking collection, that also available in the .NET framework (see BlockingCollection). The point is to illustrate how simple it is to build an event driven message system using the Monitor class in .NET to implement conditional variable. Hope you find this useful.

这篇关于条件变量C#/。NET的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆