【问题标题】:Execute a method AFTER a callback completes在回调完成后执行方法
【发布时间】:2010-05-04 12:31:10
【问题描述】:

我有一个使用 C++ DLL 的 C# 应用程序。 C++ DLL 非常简单。我可以调用一种方法,它有一个回调方法。回调方法必须完成才能处理下一项。

问题是,我一次只能处理一个命令,但我想尽快处理它们。

c++ DLL 的假/简化代码接口:

void AddNumbers(int a, int b, AddNumbersCallback callback);

现在让我们尝试使用它:

void DoStuff()
{
     if(MyCollection.HasStuff)
          AddNumbers(MyCollection.First().a, MyCollection.First.b, StuffDone);
}

void StuffDone(int result)
{
    //I wish I could process the next item here, but the callback isn't done!
    //DoStuff();
}

问题的根源是我想在回调完成之后执行代码

我的临时解决方案是在线程池中排队一个项目,然后等待 100 毫秒。通常,这会给方法“完成”的时间。

“不”,我无法更改 DLL。

【问题讨论】:

  • DoStuff() 作为StuffDone 的最后一行而不是“之后”有什么不同?
  • 如果在回调完成之前再次调用该函数会发生什么?它似乎违背了“异步”的整个定义,以及整个 C# 中回调函数的含义,它需要你等待。
  • 在 DoStuff 和 StuffDone 中使用 Console.WriteLine(Thread.CurrentThread.ManagedId)。如果你得到不同的数字,那么你就有一个无法可靠解决的问题。如果您不这样做,那么只需在 AddNumbers() 调用之后运行代码。

标签: c# asynchronous callback


【解决方案1】:

如果函数是真正异步的,那么调用它的次数或两次调用之间的等待时间都无关紧要。 (阅读:您的 DLL 已损坏。)在这种情况下,如果您真的需要同步,您可能希望在循环中使用 EventWaitHandle。

using System.Threading;

EventWaitHandle done = new EventWaitHandle(false, EventResetMode.AutoReset);

void DoStuff()
{
    while (MyCollection.HasStuff)
    {
        // note: something smelled fishy here.
        // i assume your collection removes the first entry when you call First
        var first = MyCollection.First();
        AddNumbers(first.a, first.b, StuffDone);
        done.WaitOne();
    }
}

void StuffDone(int result)
{
    done.Set();
}

【讨论】:

  • 但这能保证“done.WaitOne();”在“StuffDone”完成之前,行不会让执行继续?问题似乎在于,“StuffDone”必须从调用堆栈中退出,然后我才能处理下一个项目。
  • 如果事先不知道两个线程的线程句柄,你就不能真正保证这样的事情,没有一个值得花钱的 DLL 会依赖你编码。我在想也许 DLL 并不是真正的异步(它只是在完成时调用回调),并且有很多条目,从回调中调用 DoStuff() 会溢出堆栈。 EventWaitHandle 的东西应该考虑这种情况,以及当事情真正异步并且您正在等待您在 StuffDone 中进行的任何处理时。
  • 这对我很有用。 “WaitOne”非常好用。
猜你喜欢
  • 1970-01-01
  • 2020-01-27
  • 2015-12-04
  • 2018-10-30
  • 2013-07-07
  • 2017-06-07
  • 2021-05-20
  • 2011-09-07
相关资源
最近更新 更多