【问题标题】:2nd BeginInvoke call claims already completed. Why?第二个 BeginInvoke 调用声明已经完成。为什么?
【发布时间】:2011-04-16 10:49:26
【问题描述】:

我用 BeginInvoke 反复调用一个方法。每次通话后,我都会调用 EndInvoke。

问题在于,对于第二次调用,返回的 IAsyncResult 中的 IsCompleted 成员在 BeginInvoke 调用之后立即设置为 true。

这会导致故障,因为程序会认为第二次调用已完成。

为什么要这样做,我如何检测第二次调用何时真正完成?

Declarations:
IAsyncResult ar;
Mercury.J4000.Ui.frmMain.doPrintsDelegate printCallback;


The BeginInvoke call:
ar = printCallback.BeginInvoke (jobNameArray, copies, distances, null, null);


The EndInvoke call (in another method):
printCallback.EndInvoke(ar);

【问题讨论】:

  • 您介意分享您的代码吗?
  • 请出示代码。不要让我们猜你做错了什么。
  • 用代码更新您的问题,而不是将其作为评论发布。
  • 您需要发布可以重现问题的代码。

标签: c# .net multithreading begininvoke iasyncresult


【解决方案1】:

我的猜测是您在两次调用中都使用了相同的“ar”变量,因为您已将其声明为字段。每个调用都应该有自己的实例;将字段声明为 List<IAsyncResult> 并编写必要的管道来初始化它并将每个结果与每个调用相关联。您没有提供足够的代码让我们帮助您完成该部分(实际上这个答案是一个猜测,因为您没有提供足够的代码。)

【讨论】:

  • 是的,我使用的是同一个变量,因为 Microsoft 文档中关于 EndInvoke 参数的说明如下:“表示特定调用异步操作的 IAsyncResult,在调用 BeginInvoke 时返回。”
  • @alankdkd“代表一个特定的invoke异步操作”意味着每次调用BeginInvoke时都需要一个新的变量来跟踪结果。
  • @alankdkd - 那么请将我的回复标记为答案(因为吉姆在我之后 10 分钟回答了相同的答案)
【解决方案2】:

我假设你正在做这样的事情:

IAsyncResult ar;
ar = printCallback.BeginInvoke(...);
// do some other stuff
ar = printCallback.BeginInvoke(...);

如果第一个异步操作在第二个异步操作开始之前没有完成,那么您将丢失 IAsyncResult 值。它被第二次调用覆盖。

不知何故,您必须跟踪各个 IAsyncResult 引用并将它们与您进行的调用相关联。如果您只有一两个,您可以轻松跟踪单个变量或集合(通常是List 或数组)。

这个问题可能会对你有所帮助:Can I use a single instance of a delegate to start multiple Asynchronous Requests?

我还建议您考虑为异步委托使用回调。这样,正确的IAsyncResult 将作为参数传递给回调,并且不会产生歧义。但是,使用 AsyncCallback 可能需要对代码进行重大重构。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-01
    • 2015-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多