答:隱式連結**無法在代碼中指定 DLL 路徑**。Windows 載入器按固定順序搜尋:
GetSystemDirectory,通常 C:\Windows\System32)GetWindowsDirectory)對策:將 DLL 放在 EXE 同目錄 (最推薦) 或系統目錄。若需自定路徑,必須改用 顯式連結 (LoadLibrary 指定完整路徑)。
答:完全可以。多線程是 OS 能力,與程式類型 (EXE/DLL) 無關。DLL 內建立線程與 EXE 相同。
// DLL 全域
CEvent g_hSendEvent; // 手動重置事件
SOCKET g_sendSock = INVALID_SOCKET;
// 發送線程函數
DWORD WINAPI SendThreadFunc(LPVOID) {
g_sendSock = socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in dest = {AF_INET, htons(DEST_PORT), inet_addr(DEST_IP)};
while (1) {
WaitForSingleObject(g_hSendEvent, INFINITE); // 等待觸發
g_hSendEvent.ResetEvent();
// 從佇列取資料 sendto...
}
closesocket(g_sendSock);
return 0;
}
// 匯出介面:初始化 (DLL 載入時**不可**建立線程!)
extern "C" __declspec(dllexport) bool Initialize() {
// 建立線程
DWORD tid; HANDLE h = CreateThread(NULL, 0, SendThreadFunc, NULL, 0, &tid);
return h != NULL;
}
// 匯出介面:提交資料觸發發送
extern "C" __declspec(dllexport) void SendData(const char* buf, int len) {
// 複製資料到佇列...
g_hSendEvent.SetEvent(); // 喚醒發送線程
}
// 匯出介面:清理 (進程卸載 DLL 時呼叫)
extern "C" __declspec(dllexport) void Cleanup() {
g_hSendEvent.SetEvent(); // 確保線程退出等待
// 等待線程結束...
}
在 DllMain 的 DLL_PROCESS_ATTACH 中建立線程會導致 **死鎖** (載入器鎖)。必須提供顯式 Initialize() 介面讓應用程式在載入完成後呼叫。
int CMyDllApp::ExitInstance() {
// 發送結束信號、等待線程、關閉 Socket
g_hSendEvent.SetEvent();
WaitForSingleObject(g_hThread, INFINITE);
return CWinApp::ExitInstance();
}