- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
代码如下:
class LongOp
{
//The delegate
Action longOpDelegate = LongOp.DoLongOp;
//The result
string longOpResult = null;
//The Main Method
public string CallLongOp()
{
//Call the asynchronous operation
IAsyncResult result = longOpDelegate.BeginInvoke(Callback, null);
//Wait for it to complete
result.AsyncWaitHandle.WaitOne();
//return result saved in Callback
return longOpResult;
}
//The long operation
static void DoLongOp()
{
Thread.Sleep(5000);
}
//The Callback
void Callback(IAsyncResult result)
{
longOpResult = "Completed";
this.longOpDelegate.EndInvoke(result);
}
}
这是测试用例:
[TestMethod]
public void TestBeginInvoke()
{
var longOp = new LongOp();
var result = longOp.CallLongOp();
//This can fail
Assert.IsNotNull(result);
}
如果运行,测试用例可能会失败。为什么?
关于 delegate.BeginInvoke 如何工作的文档很少。有没有人想分享任何见解?
更新这是一个微妙的竞争条件,在 MSDN 或其他地方没有很好的记录。正如接受的答案中所解释的那样,问题是当操作完成时,等待句柄发出信号,然后执行回调。该信号释放等待的主线程,现在 Callback 执行进入“竞赛”。 Jeffry Richter's suggested implementation显示幕后发生的事情:
// If the event exists, set it
if (m_AsyncWaitHandle != null) m_AsyncWaitHandle.Set();
// If a callback method was set, call it
if (m_AsyncCallback != null) m_AsyncCallback(this);
有关解决方案,请参阅 Ben Voigt 的回答。该实现不会产生第二个等待句柄的额外开销。
最佳答案
ASyncWaitHandle.WaitOne() 在异步操作完成时发出信号。同时调用 CallBack()。
这意味着 WaitOne() 之后的代码在主线程中运行,而 CallBack 在另一个线程中运行(可能与运行 DoLongOp() 的线程相同)。这会导致竞争条件,其中 longOpResult 的值在返回时基本上是未知的。
人们可能期望 ASyncWaitHandle.WaitOne() 会在 CallBack 完成时发出信号,但这不是它的工作方式;-)
您需要另一个 ManualResetEvent 让主线程等待 CallBack 设置 longOpResult。
关于c# - IAsyncResult.AsyncWaitHandle.WaitOne() 在回调之前完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4099318/
(只能使用 .NET 3.5 stock,所以没有任务,没有响应式扩展) 我有,我认为这是一个简单的案例,但我对此感到困惑。 简而言之,我将 BeginGetRequestStream 的 IAsyn
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
为什么 IAsyncResult 要求我保留对 BeginInvoked 的委托(delegate)的引用? 我希望能够写出这样的东西: new GenericDelegate(DoSomething
我在 .net WPF 中编程。 我有一个(第三方)API,它实现了开始/结束异步调用模式。 BeginWork() 函数返回一个 IAsyncResult。 但是,一旦完成,没有明显的方法可以取消/
在WaitAll的一些实现中我看到了下面的代码 IAsyncResult result1 = Method.BeginInvoke(10, MyCallback, null) IAsyncResult
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
我最近刚接触到 IAsyncResult 并且已经使用了很长时间。我真正想知道的是,当我们有更好的替代 ThreadPool 方法时,为什么还要使用 IAsyncResult?从我目前对两者的理解来看
我使用 Action.BeginInvoke()方法,这是否使用线程池? 我有以下 C# 代码: List hashList1 = hashList.Where((x, ind) => ind
我通常对部分实现接口(interface)持谨慎态度。但是,IAsyncResult 有点特殊,因为它支持几种完全不同的使用模式。您使用/查看使用 AsyncState/AsyncCallback 模
我正在实现一个接口(interface),该接口(interface)需要实现 BeginDoSomething 和 EndDoSomething 方法。然而,我的 DoSomething 并不是真正
我正在使用一些使用 IAsyncResult 模式的旧代码。已经为 Begin- 和 End- 操作定义了委托(delegate)。我应该如何将它们重构为基于任务而不用担心委托(delegate)的实
在异步编程模型中,似乎有 4 种方式(如 Calling Synchronous Methods Asynchronously 中所述)进行异步方法调用。 调用 EndInvoke() 方法使调用线程
当我异步调用一个方法时(使用模式 BeginXxx/EndXxx),我在调用 BeginXxx 后得到一个 IAsyncResult 结果。如果方法 BeginXxxx 或 EndXxx 均未引用结果
我需要创建等待 IAsyncResult 方法完成的机制。我怎样才能做到这一点? IAsyncResult result = _contactGroupServices.BeginDeleteCont
我正在进行 REST 调用,服务器端响应采用 XML 格式。我正在异步进行此调用。我已经将它作为控制台应用程序进行了测试,它可以正常工作。但是,当我在 XBOX 上测试它时,异步请求永远不会完成。我的
几周来我一直在苦恼,我需要一些帮助。这是一个将 RDL 文件复制到项目站点的 SharePoint 实用程序。为什么我的 IAsyncResult.EndInvokes 在处理完整个列表后被调用?平均
我正在考虑为我创建的类增加一些灵 active ,该类建立与远程主机的连接,然后执行信息交换(握手)。当前实现提供了一个 Connect 函数,该函数建立连接,然后阻塞等待 ManualResetEv
我有一个正在运行的 WCF 服务,我在解决方案资源管理器中使用添加服务引用添加了对该服务的引用,并选中了创建异步操作的框。 我的调用工作正常,我有一个双向 channel 从服务器报告一些事件,我正在
如果我想继承 ChannelBase,WCF 需要我实现 IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, obje
我需要以下方面的帮助。这与异步套接字有关。 来自发件人: string stringData = "Welcome to my server server server"; byte[] messag
我是一名优秀的程序员,十分优秀!