【发布时间】:2016-06-02 14:47:49
【问题描述】:
下面是 System.IO.FileStream.BeginRead 方法在 .NET 2.0 中的实现。
如您所见,实现将操作传递给ReadDelegate 的BeginInvoke 方法。
但是,在这样做之前,它会初始化一个AutoResetEvent,然后在其上调用WaitOne。
但是,我看不出ReadDelegate 是如何向AutoResetEvent 发出信号的,因为它不会引用它。
您能解释一下这是如何工作的吗?
[HostProtection(SecurityAction.LinkDemand, ExternalThreading=true)]
public virtual IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
if (!this.CanRead)
{
__Error.ReadNotSupported();
}
Interlocked.Increment(ref this._asyncActiveCount);
ReadDelegate delegate2 = new ReadDelegate(this.Read);
if (this._asyncActiveEvent == null)
{
lock (this)
{
if (this._asyncActiveEvent == null)
{
this._asyncActiveEvent = new AutoResetEvent(true);
}
}
}
this._asyncActiveEvent.WaitOne();
this._readDelegate = delegate2;
return delegate2.BeginInvoke(buffer, offset, count, callback, state);
}
【问题讨论】:
-
AutoResetEvent从一开始就在信号状态下创建(这就是true的用途),因此如果事件刚刚创建,.WaitOne()会立即返回。这是答案的一半——另一个是解释.WaitOne()的用途,如果事件已经存在(确保一次只能读取一次?) -
这个源码是反编译的结果吗?
-
@YacoubMassad 是的。我在 Reflector 中看到过。
-
@JeroenMostert 让我感到困惑的另一件事是,MSDN 中的许多示例还将
AutoResetEvent的初始状态设置为 true 并且仍然等待它然后发出信号,同时暗示wait 阻塞当前线程,直到事件被显式发出信号。我仍然对initialState的用途感到困惑。你所说的直观是有道理的,但 MSDN 让我感到困惑。考虑这个例子。请参阅示例代码中的event_1:msdn.microsoft.com/en-us/library/… -
听起来可能是第二个问题。 :-) 但是,一般来说,您应该在 MSDN 示例中放很少的库存——它们通常是微不足道的、令人困惑的、不正确的或三者的任意组合。这个特定的示例虽然没有错,但只是为了说明行为——它并不代表一个实际的用例。在任何情况下,在信号状态下创建的
AutoResetEvent在第一次调用.WaitOne()时将不会 阻塞。它将阻止后续调用,直到调用.Set()。
标签: c# .net multithreading asynchronous