WaitForMultipleObjects & Shell COM потоки
От: edton  
Дата: 14.12.19 11:29
Оценка:
Привет,
есть такой нагугленный код, который архивирует файлы используя shell com api.
вызов pToFolder->CopyHere, который и архивирует файлы, сразу возвращает управление, создавая поток(и)
Код между // **************** с помощью toolhelp функций перечисляет потоки кроме текущего и ждет их завершения.
Всё работает, но WaitForMultipleObjects возвращает управление стабильно через ~минуту после того как архив создан.
Почему такая задержка

BOOL ZIPFiles(LPTSTR lpszFolder, LPTSTR lpszZIPFilePath)
{
    if(!lpszFolder || !lpszZIPFilePath) return FALSE;

    // Create Zip file
    BYTE startBuffer[] = {80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    FILE *f = _wfopen(lpszZIPFilePath, TEXT("wb"));
    fwrite(startBuffer,sizeof(startBuffer),1,f);
    fclose(f);

    BSTR source = lpszFolder;
    BSTR dest = lpszZIPFilePath;
        
    HRESULT        hResult;
    IShellDispatch *pISD;
    Folder         *pToFolder = NULL;
    VARIANT        vDir, vFile, vOpt;

    CoInitialize(NULL);

    hResult = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void **)&pISD);

    if  (SUCCEEDED(hResult))
    {
        VariantInit(&vDir);
        vDir.vt = VT_BSTR;
        vDir.bstrVal = dest;
        hResult = pISD->NameSpace(vDir, &pToFolder);

        if (SUCCEEDED(hResult))
        {
            // Now copy source file(s) to the zip
            VariantInit(&vFile);
            vFile.vt = VT_BSTR;
            vFile.bstrVal = source;
            VariantInit(&vOpt);
            vOpt.vt = VT_I4;
            vOpt.lVal = FOF_NO_UI;

            // Copying and compressing the source files to our zip
            hResult = pToFolder->CopyHere(vFile, vOpt);
            // *************************************************************************************
            HANDLE hThrd[5]; 
                       HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPALL ,0);  //TH32CS_SNAPMODULE, 0);
                    DWORD NUM_THREADS = 0;
            if (h != INVALID_HANDLE_VALUE) {
                        THREADENTRY32 te;
                        te.dwSize = sizeof(te);
                        if (Thread32First(h, &te)) {
                            do {
                                if (te.dwSize >= (FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID)) ) {
                                    //only enumerate threads that are called by this process and not the main thread
                                    if((te.th32OwnerProcessID == GetCurrentProcessId()) && (te.th32ThreadID != GetCurrentThreadId()) ){
                                        //printf("Process 0x%04x Thread 0x%04x\n", te.th32OwnerProcessID, te.th32ThreadID);
                                        hThrd[NUM_THREADS] = OpenThread(SYNCHRONIZE/*THREAD_ALL_ACCESS*/, FALSE, te.th32ThreadID);
                                        NUM_THREADS++;
                                    }
                                }
                                te.dwSize = sizeof(te);
                            } while (Thread32Next(h, &te));
                        }
                        CloseHandle(h);
    
            //Wait for all threads to exit
                    WaitForMultipleObjects(NUM_THREADS, hThrd , TRUE , INFINITE);
    
                    //Close All handles
                    for ( DWORD i = 0; i < NUM_THREADS ; i++ ){
                           CloseHandle( hThrd[i] );
                    }
                } //if invalid handle
        // **********************************************************************************
            pToFolder->Release();
        }
        pISD->Release();
    }
    CoUninitialize();
    return TRUE;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.