c - 如何在 C 中执行 DLL 中的线程
问题描述
我创建了一个运行 3 个工作线程的 DLL,主线程处于循环中等待线程完成。线程被创建,但没有执行线程。
我尝试在使用 CreateThread() 创建的函数内设置 MessageBox 函数,但该框没有出现。我也尝试过调试,并且 CreateThread() 的返回值是有效的,所以线程被创建了。
BOOL WINAPI DllMain() {
main();
return 1;
}
int main() {
HANDLE h1, h2, h3;
h1 = CreateThread(first)...
h2 = CreateThread(second)...
h3 = CreateThread(third)...
WaitForSingleObject(h3, INFINITE);
return 1;
}
first() {
MessageBoxA("print some stuff");
return;
}
我已经包含了一些关于我的布局的伪代码。由于它的敏感性,我无法提供真实的代码。然而,这就是正在发生的事情。我在另一个加载此 .DLL 的项目中使用 LoadLibrary。DLL 被加载并执行 DllMain。然后它调用我的 main 函数来创建 3 个线程。每个线程都被创建。但是线程内部的内容不会执行。
编辑:
// dllmain.cpp : Defines the entry point for the DLL application.
#include <Windows.h>
void mb() {
MessageBoxW(0, L"AAAAAAAAAAAAAAAAAAAAAAAAA", L"AAAAAAAAAAAAAAAAAAAAAAa", 1);
}
void create() {
HANDLE han;
DWORD threadId;
han = CreateThread(NULL, 0, mb, NULL, 0, &threadId);
han = CreateThread(NULL, 0, mb, NULL, 0, &threadId);
han = CreateThread(NULL, 0, mb, NULL, 0, &threadId);
}
BOOL APIENTRY DllMain() {
create();
return 1;
}
解决方案
因为在一般情况下 DLL 可以被卸载,需要添加对 DLL 的引用 - 因为它不会被卸载,直到线程使用它执行代码。这可以通过调用来完成GetModuleHandleEx
-除非指定,否则会增加模块的引用计数。GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT
当线程退出时——我们通过调用取消引用 DLL 代码FreeLibraryAndExitThread
。在大多数情况下不需要等待所有线程退出。所以代码,里面的dll可以是下一个
ULONG WINAPI DemoThread(void*)
{
MessageBoxW(0, L"text", L"caption", MB_OK);
// dereference dlll and exit thread
FreeLibraryAndExitThread((HMODULE)&__ImageBase, 0);
}
void someFnInDll()
{
HMODULE hmod;
// add reference to dll, because thread will be use it
if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (PCWSTR)&__ImageBase, &hmod))
{
if (HANDLE hThread = CreateThread(0, 0, DemoThread, 0, 0, 0))
{
CloseHandle(hThread);
}
else
{
// dereference dll if thread create fail
FreeLibrary(hmod);
}
}
}
wait inside dll 入口点是错误的,因为我们在这里持有进程范围的临界区。如果我们等待线程退出——这个等待总是死锁——线程在退出(并开始)之前尝试进入这个临界区,但不能因为我们在这里等他。所以我们持有临界区并等待线程,但是当我们退出这个临界区时线程会等待。僵局
推荐阅读
- java - Eclipse can't find XML related classes after switching build path to JDK 10
- gcc - 调试 glibc 构建过程
- python - Windows 上的无服务器部署
- c# - 了解 getter 和 setter
- php - 无法创建数据库 PHP
- python - Python gcloud clusters get-credentials 返回权限错误
- html - HTML/CSS/引导程序 | 引导导航栏
- c# - 并行执行问题
- swagger - 如何在 Swagger 中显示查询参数的 c# 验证属性
- apache-spark - Spark 独立文件处理顺序会降低性能