首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AutoResetEvent进程?

AutoResetEvent进程?
EN

Stack Overflow用户
提问于 2011-07-19 17:02:21
回答 2查看 1.1K关注 0票数 1
代码语言:javascript
复制
private ConcurrentQueue<Data> _queue = new ConcurrentQueue<Data>();
private AutoResetEvent _queueNotifier = new AutoResetEvent(false);

public void MoreData(Data example)
{
    _queue.Enqueue(example);
    _queueNotifier.Set();
}

private void _SimpleThreadWorker()
{
    while (_socket.Connected)
    {
        _queueNotifier.WaitOne();
        Data data;
        if (_queue.TryDequeue(out data))
        {
            //handle the data
        }
    }
}

一旦我让事件退出队列,我是否必须将事件设置为false,或者当事件返回_queueNotifier.WaitOne()或其工作方式时,事件会自动返回false吗?

我应该像下面的例子那样使用内部,还是两种方式都很好?

代码语言:javascript
复制
while (_socket.Connected)
{
    _queueNotifier.WaitOne();
    while (!_queue.IsEmpty)
    {
        Data data;
        if (_queue.TryDequeue(out data))
        {
            //handle the data
        }
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-07-19 17:05:19

如果您使用的是.NET 4中的ConcurrentQueue,最好避免完全自己处理AutoResetEvent。相反,可以创建一个BlockingCollection来包装ConcurrentQueue并使用它-它可以做您需要的所有事情。(如果您只是使用无参数构造函数创建一个BlockingCollection,它无论如何都会为您创建一个ConcurrentQueue。)

编辑:如果你真的想继续使用AutoResetEvent,那么WaitOne会自动(原子地)重置事件--这是AutoResetEvent的“自动”部分。与ManualResetEvent相比,它不会重置事件。

票数 4
EN

Stack Overflow用户

发布于 2011-07-19 17:13:36

当您执行_queueNotifier.Set()时,事件变成有信号的。当用信号通知事件并从另一个线程调用_queueNotifier.WaitOne()时,两件事同时发生(即在内核模式下):

未阻止该事件(因为它的auto-reset)

  • The线程调用WaitOne is

因此,您不必自己显式设置事件状态。

然而,正如Jon所说,如果您对共享变量所做的唯一事情就是从队列中推送和拉出项,那么简单地使用BlockingCollection会更方便。

如果您正在访问多个共享变量,那么使用单线程同步机制(您自己的)可能是有意义的。

此外,在我看来,如果您要使用自己的代码,最好这样做:

代码语言:javascript
复制
public void MoreData(Data example)
{
    var queueWasEmpty = _queue.IsEmpty;
    _queue.Enqueue(example);
    if (queueWasEmpty) {
        _queueNotifier.Set();
    }
}

private void _SimpleThreadWorker()
{
    while (_socket.Connected)
    {
        _queueNotifier.WaitOne();
        Data data;
        while(!queue.IsEmpty) {
            if (_queue.TryDequeue(out data))
            {
                //handle the data
            }
        }
    }
}

这样,您就不必在消费者函数繁忙时将项目添加到队列中时进入内核模式(来设置事件)。您还可以避免在消费者函数的每次迭代中进入内核模式。

确实,对于后者,避免上下文切换是以添加_queue.IsEmpty测试为代价的(其中一个糟糕的实现可能无论如何都会进行上下文切换);然而,这种实现很可能是作为互锁的比较交换操作实现的,它不需要进入内核模式。

免责声明:我没有检查源代码或IL来验证上述信息。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6744675

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档