如何避免阻塞(C++、Win32)

Posted

技术标签:

【中文标题】如何避免阻塞(C++、Win32)【英文标题】:How to avoid blocking (C++, Win32) 【发布时间】:2009-03-18 06:14:47 【问题描述】:

我正在制作一个必须响应应用程序请求的 dll。应用程序的要求之一是调用不应花费很长时间才能完成。

比方说,我有一个函数 foo(),它被宿主应用程序调用:

int foo(arg)
    // some code i need to execute, say,
    LengthyRoutine();
    return 0;

比方说,foo 必须执行一个肯定需要很长时间的任务(或调用一个函数)。该应用程序允许我设置一个等待变量;如果 foo 返回时此变量非零,它会一次又一次地调用 foo(在每次调用之前重置等待变量)直到等待返回 0。

最好的方法是什么?

我去吗:

int foo(arg)

    if (inRoutine == TRUE) 
        wait = 1;
        return 0;
     else 
        if (doRoutine == TRUE) 
             LengthyRoutine();
             return 0;
        
    

    return 0;

这并不能真正解决 LongyRoutine 需要很长时间才能完成的问题。我是否应该根据它是否完成任务来生成某种类型的线程来更新 inRoutine?

谢谢..

【问题讨论】:

【参考方案1】:

生成另一个线程几乎是最好的方法,只需确保在设置表示您已完成的变量之前设置结果变量以避免竞争条件。如果经常调用它,您可能希望提前生成一个工作线程并重用它以避免线程启动开销。

还有另一种可能的解决方案,每次调用函数时都做部分工作,但是这会在 DLL 中花费更多时间并且可能不是最佳的,而且对于大多数算法来说实现工作代码也更复杂.

【讨论】:

谢谢埃里克。我以前从未尝试过制作线程,并且觉得这很难做到。我会试一试:) 这绝对是最好的选择,但正如 Eric 所说,要小心线程同步 我还不太了解线程同步的问题。我只需要一个执行例程的工作线程,在整个执行过程中的某些点更新状态变量。然后,调用应用程序会定期检查这些变量以了解该做什么。这个可以吗?有没有... ... 我必须注意的问题?我应该使用 MFC CreateThread 吗?谢谢.. 同步不应该是一个主要问题,只要从工作函数中的哪个点读取变量无关紧要,(如果只是进度百分比,我不会太担心) 如果这是一个问题,一个简单的锁可能会正常工作。【参考方案2】:

如果是 C 编程,使用回调 - 将回调传递给 foo。您必须就回调签名达成一致,并在 LongyRoutine 中的工作完成时进行一些内务处理以触发它。

typedef (void) callbackFunction(void);

int foo(arg, callbackFunction)

   // some code i need to execute, say,
   // register callback and return right away
   // Trigger the LengthyRoutine to run after this function returns

   return 0;


LengthyRoutine()

   // do lenghty routine

   // now inform the caller with their suppiled callback
   callbackFunction();

本质上是Observer C 中的模式。在我看来,C++ 使工作变得更容易/更干净

【讨论】:

这似乎是一个可行的选择。我对回调还不太了解,但与线程相比,它似乎更容易实现。+1 @krebstar:请注意,回调机制并没有消除对工作线程的需求——它只是取代了对函数的多次调用,直到漫长的过程完成。你需要一个工作线程。【参考方案3】:

如果在极少数情况下LengthyRoutine() 不是第 3 方代码并且您拥有所有源代码并且可以拆分它,那么您可以考虑使用coroutines。

【讨论】:

嗯,LengthyRoutine 其实就是对第三方代码的一组调用;可以拆分任务。但是,需要很长时间才能完成的原因是因为它受 IO 限制(等待另一个组件完成其任务)。对不起,我没有在我的问题中解释这一点。 好的,听起来你需要一个单独的线程或进程然后:-)

以上是关于如何避免阻塞(C++、Win32)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Win32 上开始使用 C++ 编程?

在 C# 中访问 Process.MainModule.FileName 时如何避免 Win32 异常?

如何在 win32 gui 应用程序中使用另一个事件循环

如何使用 Win32 句柄在 C++ 中获取文件名? [复制]

如何将结构从 C++ 应用程序传递到 C++ Win32 DLL?

如何设置win32 api c++按钮背景颜色和文本颜色?