Как уже отмечалось, в случаях, когда тест завершается успешно, вам просто повезло, что потоки чередуются таким образом, что обратный вызов вызывается до того, как произойдет вызов EndInvoke
. Правильный шаблон APM - это вызов EndWriteLine внутри обратного вызова, что означает, что вы должны передать AsyncLineWriter
как часть состояния методу BeginInvoke
.
РЕДАКТИРОВАТЬ: есть дополнительное осложнение, поскольку обратный вызов может произойти после того, как IAsyncResult
WaitHandle
сигнализируется. Так что это не значит, что обратный вызов не вызывается, он вызывается только после проверки. Это исправляет это:
AsyncLineWriter lineWriter = new AsyncLineWriter();
Object myState = new Object();
object[] state = new object[2];
state[0] = lineWriter;
state[1] = myState;
object callbackState = null;
ManualResetEvent evnt = new ManualResetEvent(false);
AsyncCallback callback = (r) =>
{
Object[] arr = (Object[])r.AsyncState;
LineWriter lw = (LineWriter)arr[0];
Object st = arr[1];
callbackState = st;
lw.EndWriteLine(r);
evnt.Set();
};
// Act
IAsyncResult asyncResult = lineWriter.BeginWriteLine("test", callback, state);
//asyncResult.AsyncWaitHandle.WaitOne(); -- callback can still happen after this!
evnt.WaitOne();
//Assert
Assert.AreSame(myState, callbackState);