为什么这个 AsyncCallback 测试有时会失败?
我有以下类尝试充当简单的异步操作:
public class AsyncLineWriter
{
private delegate void SynchronousWriteLineDelegate(string message);
private SynchronousWriteLineDelegate DoWriteLine;
private void SynchronousWriteLine(string message)
{
Console.WriteLine(message);
}
public AsyncLineWriter()
{
DoWriteLine = new SynchronousWriteLineDelegate(SynchronousWriteLine);
public IAsyncResult BeginWriteLine(string message, AsyncCallback callback, object state)
{
return DoWriteLine.BeginInvoke(message,callback,state);
}
public void EndWriteLine(IAsyncResult asyncResult)
{
DoWriteLine.EndInvoke(asyncResult);
}
}
以下单元测试间歇性失败,但我不明白竞争条件在哪里:
[TestMethod]
public void Callback_is_called()
{
// Arrange
AsyncLineWriter lineWriter = new AsyncLineWriter();
object state = new object();
object callbackState = null;
AsyncCallback callback = (r) =>
{
callbackState = r.AsyncState;
};
// Act
IAsyncResult asyncResult = lineWriter.BeginWriteLine("test", callback, state);
lineWriter.EndWriteLine(asyncResult);
// Assert
Assert.AreSame(state, callbackState);
}
I have the following class which tries to act as a simple asynchronous operation :
public class AsyncLineWriter
{
private delegate void SynchronousWriteLineDelegate(string message);
private SynchronousWriteLineDelegate DoWriteLine;
private void SynchronousWriteLine(string message)
{
Console.WriteLine(message);
}
public AsyncLineWriter()
{
DoWriteLine = new SynchronousWriteLineDelegate(SynchronousWriteLine);
public IAsyncResult BeginWriteLine(string message, AsyncCallback callback, object state)
{
return DoWriteLine.BeginInvoke(message,callback,state);
}
public void EndWriteLine(IAsyncResult asyncResult)
{
DoWriteLine.EndInvoke(asyncResult);
}
}
The following unit test is intermittently failing, but I don't understand where the race condition is:
[TestMethod]
public void Callback_is_called()
{
// Arrange
AsyncLineWriter lineWriter = new AsyncLineWriter();
object state = new object();
object callbackState = null;
AsyncCallback callback = (r) =>
{
callbackState = r.AsyncState;
};
// Act
IAsyncResult asyncResult = lineWriter.BeginWriteLine("test", callback, state);
lineWriter.EndWriteLine(asyncResult);
// Assert
Assert.AreSame(state, callbackState);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在此模式中,回调在线程池线程上运行,您应该从回调中调用
EndInvoke
。EndInvoke
不会等待回调完成(因为这会导致死锁),因此回调和测试方法之间存在竞争。编辑:等待句柄也可以在回调完成之前设置。试试这个:
In this pattern, the callback is run on a thread pool thread and you are supposed to call
EndInvoke
from within the callback.EndInvoke
doesn't wait for the callback to complete ( because this would cause a deadlock ), so you have a race between the callback and your test method.EDIT: The wait handle can be set before the callback has completed too. Try this:
如前所述,在测试成功的情况下,您只是幸运,线程以这样的方式交错,即在对
EndInvoke
的调用发生之前调用回调。正确的 APM 模式是在回调中调用 EndWriteLine,这意味着您必须将AsyncLineWriter
作为状态的一部分传递给BeginInvoke
方法。编辑:有一个额外的复杂性,因为回调可能发生在
IAsyncResult
WaitHandle
发出信号之后。因此,并不是回调没有被调用,而是在检查发生后被调用。这修复了它:As already noted, on the occasions where the test succeeds you're just being lucky that the threads are interleaving in such a way that the callback gets called before the call to
EndInvoke
occurs. The proper APM pattern is to call your EndWriteLine within the callback which means that you have to pass theAsyncLineWriter
as part of the state to theBeginInvoke
method.EDIT: there's an extra complication since the callback can occur after the
IAsyncResult
WaitHandle
is signalled. So it's not that the callback doesn't get called it's just getting called after the check occurs. This fixes it: