C# 自动还原过程?
如果您使用的是.NET4中的ConcurrentQueue,最好避免完全由您自己处理AutoResetEvent。相反,创建一个包来包装ConcurrentQueue并使用它——它可以完成您所需要的一切。如果您只是使用无参数构造函数创建一个BlockingCollection,它无论如何都会为您创建一个ConcurrentQueue 编辑:如果你真的想继续使用AutoResetEvent,那么WaitOne会自动自动重置事件-这是AutoResetEvent的自动部分。将此与ManualResetEvent进行比较,ManualResetEvent不会重置事件。如果使用.NET 4中的ConcurrentQueue,最好避免完全自己处理自动重置事件。相反,创建一个包来包装ConcurrentQueue并使用它——它可以完成您所需要的一切。如果您只是使用无参数构造函数创建一个BlockingCollection,它无论如何都会为您创建一个ConcurrentQueue 编辑:如果你真的想继续使用AutoResetEvent,那么WaitOne会自动自动重置事件-这是AutoResetEvent的自动部分。将此与ManualResetEvent进行比较,ManualResetEvent不会重置事件。执行此操作时,queueNotifier.Set事件将发出信号。当发出事件信号并从另一个线程调用_queueNotifier.WaitOne时,两件事同时发生,即在内核模式下: 自事件自动重置后,该事件变为未标记 调用WaitOne的线程已解除阻止 因此,您不必自己显式设置事件状态 然而,正如Jon所说,如果您对共享变量所做的唯一事情就是从队列中推拉项目,那么简单地使用BlockingCollection就更方便了 如果您正在访问多个共享变量,那么有一个您自己的单线程同步机制可能是有意义的 此外,在我看来,如果您要使用自己的代码,最好执行以下操作:C# 自动还原过程?,c#,autoresetevent,concurrent-collections,C#,Autoresetevent,Concurrent Collections,如果您使用的是.NET4中的ConcurrentQueue,最好避免完全由您自己处理AutoResetEvent。相反,创建一个包来包装ConcurrentQueue并使用它——它可以完成您所需要的一切。如果您只是使用无参数构造函数创建一个BlockingCollection,它无论如何都会为您创建一个ConcurrentQueue 编辑:如果你真的想继续使用AutoResetEvent,那么WaitOne会自动自动重置事件-这是AutoResetEvent的自动部分。将此与ManualRese
while (_socket.Connected)
{
_queueNotifier.WaitOne();
while (!_queue.IsEmpty)
{
Data data;
if (_queue.TryDequeue(out data))
{
//handle the data
}
}
}
这样,您就不必进入内核模式来设置事件,只要在使用者函数繁忙时将项目添加到队列中。在消费函数的每次迭代中,您还可以避免进入内核模式
确实,对于后者,避免上下文切换是以添加_queue.i空测试为代价的,在该测试中,一个糟糕的实现可能会执行上下文切换;然而,这可能是作为一个互锁的比较交换操作实现的,它不需要进入内核模式
免责声明:我没有检查源代码或IL以验证上述信息。当您执行queueNotifier.Set时,事件将变为信号。当发出事件信号并从另一个线程调用_queueNotifier.WaitOne时,两件事同时发生,即在内核模式下:
自事件自动重置后,该事件变为未标记
调用WaitOne的线程已解除阻止
因此,您不必自己显式设置事件状态
然而,正如Jon所说,如果您对共享变量所做的唯一事情就是从队列中推拉项目,那么简单地使用BlockingCollection就更方便了
如果您正在访问多个共享变量,那么有一个您自己的单线程同步机制可能是有意义的
此外,在我看来,如果您要使用自己的代码,最好执行以下操作:
while (_socket.Connected)
{
_queueNotifier.WaitOne();
while (!_queue.IsEmpty)
{
Data data;
if (_queue.TryDequeue(out data))
{
//handle the data
}
}
}
这样,您就不必进入内核模式来设置事件,只要在使用者函数繁忙时将项目添加到队列中。在消费函数的每次迭代中,您还可以避免进入内核模式
确实,对于后者,避免上下文切换是以添加_queue.i空测试为代价的,在该测试中,一个糟糕的实现可能会执行上下文切换;然而,这可能是作为一个互锁的比较交换操作实现的,它不需要进入内核模式
免责声明:我没有检查源代码或IL来验证上述信息。我会检查,但我仍然有兴趣了解AutoResetEvent如何工作,以便在将来再次需要时进一步了解它。@Prix:已编辑以包含该信息。有关更多信息,请参阅AutoResetEvent的文档。感谢您的更新,关于您刚开始所说的,我对将concurrentqueue包装在blockingcollection中有点困惑,使用blockingcollection是否更容易?如果您可以,我希望能提供一些示例,以便更好地理解您的意思…@Prix:BlockingCollection总是包装另一个集合-但是如果您只是创建一个新的BlockingCollection而没有指定要包装的集合,它将自动使用ConcurrentQueue。我建议您阅读BlockingCollection的文档,其中给出了如何使用它的示例等。我将对此进行检查,但我仍然有兴趣了解AutoResetEvent如何工作
如果我将来再次需要它,请进一步了解它。@Prix:已编辑以包含该信息。有关更多信息,请参阅AutoResetEvent的文档。感谢您的更新,关于您刚开始所说的,我对将concurrentqueue包装在blockingcollection中有点困惑,使用blockingcollection是否更容易?如果您可以,我希望能提供一些示例,以便更好地理解您的意思…@Prix:BlockingCollection总是包装另一个集合-但是如果您只是创建一个新的BlockingCollection而没有指定要包装的集合,它将自动使用ConcurrentQueue。我建议您阅读BlockingCollection的文档,其中给出了如何使用它的示例等。
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
}
}
}
}