简体   繁体   English

如何克服阻塞的第三方功能

[英]How to overcome a blocking 3rd party function

I am using some 3rd party functions (hrmcom.dll) in my win32 application. 我在Win32应用程序中使用了一些第三方功能(hrmcom.dll)。 I have a main windowclass with a winproc and 3 childwindows, all of a second windowclass that share one childproc. 我有一个带有winproc和3个子窗口的主windowclass,所有第二个共享一个childproc的windowclass。 The call to the 3rd party functions is in one of the childwindows and handled in the childproc based on a WM_COMMAND (a button is pushed and the functions are called). 对第三方函数的调用是在一个子窗口中进行的,并在子进程中基于WM_COMMAND进行处理(按下按钮并调用函数)。

One of these functions is blocking. 这些功能之一是阻止。 It makes connection to a IrDA device and it 'hangs' when the device is not present and in connect mode. 它与IrDA设备建立连接,并且在该设备不存在且处于连接模式时会“挂起”。 I wanted to take care of this situation with a timeout of the call. 我想通过通话超时来处理这种情况。

What I tried is to call SetTimer (call at the same window as from where the blocking function is) just before the blocking call and define a WM_TIMER handle. 我尝试的是在阻塞调用之前调用SetTimer(在与阻塞函数所在的窗口相同的窗口中调用)并定义WM_TIMER句柄。 This is not working, debugging shows that the function hangs and the WM_TIMER event is never handled. 这是行不通的,调试表明该函数已挂起并且从未处理WM_TIMER事件。 I tried to call the timer for the main window, but that is also not working. 我试图调用主窗口的计时器,但这也无法正常工作。

I saw a working example of this DLL in where one button is used for starting and cancelling the proces of connection to the device. 我看到了此DLL的一个工作示例,其中一个按钮用于启动和取消与设备的连接过程。

Question: How could I deal with the hanging function and time it out after X seconds when it is not connecting to the device? 问题:当悬吊功能未连接到设备时,如何处理并在X秒后将其超时? I have been reading about threads, but i was wondering if it really can only be done that complicated (I have not been able to get threads work so far). 我一直在阅读有关线程的文章,但我想知道它是否真的只能完成那么复杂的工作(到目前为止,我还无法使线程工作)。

Below is the header file part of the called function, if that helps: 以下是被调用函数的头文件部分,如果有帮助的话:

__declspec (dllexport) BOOL CALLBACK fnHRMCom_StartIRCommunication  (int, LPTSTR);

//  Return value:
//  BOOL bStartOK
//   TRUE           - Starting of communication made succesfully
//   FALSE          - Problems encountered, check the following possible   errors:
//                      * Communication has already been started and it is running
//                      * Communication port already reserved for some other device
//                      * Maybe call was made from 16-bit program. A 32-bit DLL cannot
//                        create an additional thread when that DLL is being called by
//                        a 16-bit program.
//
///////////////////////////////////////////////////////////////////////////////

Latest code included: The thread function (simplified): 包含的最新代码:线程函数(简体):

VOID Thread(PVOID pvoid)
{
volatile PPARAMS pparams;
pparams = (PPARAMS) pvoid;

if (pparams->bContinue)
{

    if (!fnHRMCom_ResetIRCommunication(0))
    {
        // Resetting IR connection was not successful
        ErrMsg(L"Resetting IR connection was not successful");
        return;
    }
    if (!fnHRMCom_StartIRCommunication(HRMCOM_PARAM_IRDA, L"IR"))
    {
        // IrDA couldn't be opened, stop connection thread
        fnHRMCom_EndIRCommunication(FALSE);
        ErrMsg(L"IrDA couldn't be opened, connection thread stopped");
        return;
    }
    //Status report "IR Communication started"
    SetWindowText(hwndCtrl[11], L"Status: IR Communication started");

    if (!fnHRMCom_ReadMonitorInfo(&psg, &psmi))
    {
        // Reading failed, close connection
        if (pparams->bContinue)
        {
            fnHRMCom_EndIRCommunication(FALSE);
            ErrMsg(L"Reading failed, connection closed01");
            SendMessage(hwndCtrl[8], LB_RESETCONTENT, 0, 0);
            return;
        }
        else
        {
            fnHRMCom_EndIRCommunication(FALSE);
            ErrMsg(L"Connection aborted, connection closed");
            SendMessage(hwndCtrl[8], LB_RESETCONTENT, 0, 0);
            return;
        }
    }

    }
    // End IR communication
    fnHRMCom_EndIRCommunication(FALSE);
}
_endthread();


}

Code for calling and cancelling the Thread manually: 用于手动调用和取消线程的代码:

case (ID_CTRL + 12) : 
        //Cancel connect to device
        params.bContinue = FALSE;           
        if (!fnHRMCom_EndIRCommunication(FALSE))
        {
            //TODO: Error
            return 0;
        }
        TerminateThread(hThread, 0);    
        return 0;       
    case (ID_CTRL + 7) : 
        //Load Activities from Device
        params.bContinue = TRUE;
        if (IDCANCEL != MessageBox(hwnd, L"Make sure your device is set to connectmode", L"Warning", MB_OKCANCEL | MB_ICONEXCLAMATION))
        {
            //Start downloading the activities in separate thread
            SetTimer(hwnd, IDT_TIMER1, 10000, NULL );
            hThread = (HANDLE)_beginthread(Thread, 0, &params);
        }
        //cancelled, dont start the IrDA connection thread      
        return 0;

And the code for the timer handler: 以及计时器处理程序的代码:

case WM_TIMER:
    if (LOWORD(wParam) == IDT_TIMER1)
    {
        if (!fnHRMCom_IsIrDAConnected())
        {
            SetWindowText(hwndCtrl[11], L"Status: IrDA connection timed out");
            TerminateThread(hThread, 0);
            fnHRMCom_EndIRCommunication(FALSE);
            KillTimer(hwnd, IDT_TIMER1);                
            ErrMsg(L"IrDA connection timed out");               
            return 0;
        }
        else KillTimer(hwnd, IDT_TIMER1);
    }
    return 0;

Put the blocking call into it's own thread. 将阻塞调用放入它自己的线程中。

Your threading function could be as simple as something like this: 您的线程功能可能像这样简单:

volatile BOOL success;
volatile BOOL done;

void ConnectThread() {
    success = false;
    done = false;
    if (!fnHRMCom_StartIRCommunication(123, "Some Stuff")) {
        std::cerr << "There's been some IR problem." << std::endl;
        done = true;
        return;
    }
    success = true;
    done = true;
}

Then just do your timeout outside, waiting for some signal, in this example done to be set. 然后只需在外面进行超时,等待一些信号,在此示例中done设置。 If the timeout period is over without done being set, you know that it's taking too long (and you can kill the thread), otherwise you're able to read success to determine whether it worked. 如果超时时期已经过去没有done设定,你知道它的时间太长(你可以杀死线程),否则你能够阅读success ,以确定它是否奏效。

You might also find it interesting about canceling pending i/o operations in Windows 您可能还会对在Windows中取消挂起的I / O操作感兴趣。

http://msdn.microsoft.com/en-us/library/windows/desktop/aa363789(v=vs.85).aspx http://msdn.microsoft.com/en-us/library/windows/desktop/aa363789(v=vs.85).aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用cmocka库模拟无法修改的第3方库中的函数? - How to use cmocka library to mock a function from 3rd party library which cannot be modified? 如何包装第三方DLL用于R? - How to wrap 3rd party DLL for use in R? 第三方图书馆定义/重新定义冲突 - 3rd party libraries conflicting definitions/ redefinitons 对使用开源第三方库感到困惑 - Confused in using opensource 3rd party libraries 调用第三方库函数(未作为源代码提供)是未定义的行为吗? - Is it undefined behaviour to call a 3rd party library function (not provided as source code)? 处理P / Invoking时调用函数的第三方库会导致堆损坏 - Dealing with a 3rd party library who's function call causes heap corruptions when P/Invoking 如何添加第三方库的路径? -Eclipse / Arduino - How do I the add path to a 3rd party library? - Eclipse/Arduino 如何使用正确的 dll 文件在 Cython C 扩展中启用第三方 C 库? - How do I use the correct dll files to enable 3rd party C libraries in a Cython C extension? 在C语言中,如何添加第三方库并使用Makefile从我现有的代码库中调用 - In C, how to add 3rd party Libraries and call from my existing code base using Makefile 如何在我的 gcc 编译器中链接第 3 方库 bzip2? - How can I link the 3rd party library bzip2 in my gcc compiler?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM