[英]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, ¶ms);
}
//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.