我是靠谱客的博主 敏感石头,最近开发中收集的这篇文章主要介绍多个线程共享变量的初始化问题,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、问题背景:

    写了一个USBManagerControl.dll动态库来监控USB设备的插拔事件,dllName.exe来加载调用USBManagerControl.dll。

部分代码如下:

/************
dllName.exe部分代码 begin
************/
int main()
{
    hDllInst = LoadLibrary("USBManagerControl.dll");
    //......
    if (RegisterDevNotification(3))
    {
    }
    //......
}
/************
dllName.exe部分代码 end
************/
/************
USBManagerControl.dll部分代码 begin
************/
HWND hwnd;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD
ul_reason_for_call,
LPVOID lpReserved
)
{
HANDLE thread1 = NULL;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
ben = GetModuleHandle(NULL);
thread1 = CreateThread(NULL, 0, Proc1, NULL, 0, NULL);
}
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
{
CloseHandle(thread1);
}
break;
}
return TRUE;
}
DWORD WINAPI Proc1(LPVOID lpParameter)
{
//......
hwnd = CreateWindow("firstwind", "zyc1", WS_OVERLAPPEDWINDOW, 500, 200, 600, 400, NULL, NULL, (HINSTANCE)ben, NULL);
//......
return 0;
}
bool __stdcall
RegisterDevNotification(unsigned int devInterface)
{
bool bReg = false;
for (int i = 0; i < sizeof(GUID_DEVINTERFACE)/sizeof(GUID); i++)
{
HDEVNOTIFY hDeviceNotify;
//通过注册窗口句柄hwnd的方式来监听USB设备的插拔事件
DoRegisterDeviceInterfaceToHwnd(GUID_DEVINTERFACE[i], hwnd, &hDeviceNotify);
bReg = true;
}
return bReg;
}
/************
USBManagerControl.dll部分代码 end
************/

问题:

    在VS上直接进行debug模式的调试没有问题,而直接运行编译好的dllName.exe则总是监听不到USB设备的插拔事件。

二、分析:

    在代码中添加日志,发现直接运行dllName.exe时,在dllName.exe调用DoRegisterDeviceInterfaceToHwnd时,窗口句柄为NULL,即还没有创建好。估计是在vs中直接进行debug模式的调试时,先加载了DLL,DLL里的线程thread1在dllName.exe调用注册接口时先执行了,所以窗口句柄在注册之前就已创建好。

    解决方法就是确保在执行注册窗口句柄hwnd之前,窗口句柄已经创建成功。则可以通过创建一个事件,等窗口句柄hwnd创建成功后,再通知注册窗口句柄hwnd的方式解决。修改后的代码如下:

/************
dllName.exe部分代码 begin
************/
int main()
{
    hDllInst = LoadLibrary("USBManagerControl.dll");
    //......
    if (RegisterDevNotification(3))
    {
    }
    //......
}
/************
dllName.exe部分代码 end
************/
/************
USBManagerControl.dll部分代码 begin
************/
HWND hwnd;
HANDLE g_Event;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD
ul_reason_for_call,
LPVOID lpReserved
)
{
HANDLE thread1 = NULL;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
g_Event = CreateEvent(NULL, false, false, NULL);
ben = GetModuleHandle(NULL);
thread1 = CreateThread(NULL, 0, Proc1, NULL, 0, NULL);
}
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
{
CloseHandle(thread1);
}
break;
}
return TRUE;
}
DWORD WINAPI Proc1(LPVOID lpParameter)
{
//......
hwnd = CreateWindow("firstwind", "zyc1", WS_OVERLAPPEDWINDOW, 500, 200, 600, 400, NULL, NULL, (HINSTANCE)ben, NULL);
::SetEvent(g_Event);
//......
return 0;
}
bool __stdcall
RegisterDevNotification(unsigned int devInterface)
{
bool bReg = false;
WaitForSingleObject(g_Event, INFINITE);//等待窗口句柄hwnd创建成功
for (int i = 0; i < sizeof(GUID_DEVINTERFACE)/sizeof(GUID); i++)
{
HDEVNOTIFY hDeviceNotify;
//通过注册窗口句柄hwnd的方式来监听USB设备的插拔事件
DoRegisterDeviceInterfaceToHwnd(GUID_DEVINTERFACE[i], hwnd, &hDeviceNotify);
bReg = true;
}
return bReg;
}
/************
USBManagerControl.dll部分代码 end
************/

三、总结

    如上代码所示,解决方案通过windows的CreateEvent、SetEvent 和 WaitForSingleObject 三个函数实现不同线程间事件通知的目的,从而保证在多个线程时,所有线程中的变量都初始化完成后,再执行其他操作。

最后

以上就是敏感石头为你收集整理的多个线程共享变量的初始化问题的全部内容,希望文章能够帮你解决多个线程共享变量的初始化问题所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(61)

评论列表共有 0 条评论

立即
投稿
返回
顶部