Не срабатывает mutex

205
03 июня 2018, 10:20

Всем привет! Пишу программу, которая в первом поток ищет файлы, соответствующие маске, для каждого потока создает вторичный поток, в котором подсчитывается вес файла, суммируется с остальными и выводится на экран. Проблема в том, что переменная файл постоянно перезаписывается и в случае с 3 файлами, в 3 вторичных потока передается имя только третьего файла. Для того, чтобы предотвратить это, я хочу сделать мьютекс, который не будет позволять переписать переменные и запустить новый процесс, пока в старом не выгрузятся переменные. Я написал вот такой код, догадываюсь, что он не совсем правильный, т.к. освобождение мьютекса происходит в другом потоке, а также цикл ходит, несмотря на то, что мьютекс не находится в сигнальном состоянии.

Основные фрагменты

HANDLE hMutex1 = CreateMutex(NULL, FALSE, "mymutex1");
//цикл, открывающий мьютекс
do
    if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) // is it's a file
    {
        if (GetFullPathName(lpszFileName, MAX_PATH, file, &part) == 0)
            return FALSE;
        lstrcpy(part, wfd.cFileName);
        //******************************************
        hMutex1 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mymutex1");
        WaitForSingleObject(hMutex1, INFINITE);         
        params.hWnd = hWnd;
        params.file = (LPCTSTR)file;
        thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadSize, (void*)&params, 0, NULL);
        //WaitForSingleObject(thread, INFINITE);
        //******************************************
    }
while (FindNextFile(hSearch, &wfd)); // next file in folder
//вторичный поток, в котором после выгрузки и инициализации переменных должно происходить освобождение мьютекса
DWORD WINAPI threadSize(void * param) {
    MsParams_t1 * ptr = (MsParams_t1 *)param;
    HWND hWnd = ptr->hWnd;
    LPCSTR file = ptr->file;
    ReleaseMutex(hMutex1);
    // Размер файла
    DWORD dwSize = 0;
    // Файл
    LPCTSTR lpszSystemInfo = file;
    // Открываем файл
    HANDLE hFile = CreateFile(lpszSystemInfo,
        GENERIC_READ,
        0,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_SEQUENTIAL_SCAN,
        NULL);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        MessageBox(NULL, "Не удалось открыть файл",
            "Ошибка",
            MB_OK | MB_ICONEXCLAMATION);
    }
    // Получаем размер файла
    dwSize = GetFileSize(hFile, NULL);
    if (dwSize == INVALID_FILE_SIZE)
    {
        MessageBox(NULL, "Не удалось определить размер файла",
            "Ошибка",
            MB_OK | MB_ICONEXCLAMATION);
    }
    // Закрываем файл
    CloseHandle(hFile);
    hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mymutex");
    WaitForSingleObject(hMutex, INFINITE);
    sumsize += dwSize;
    char chSize[256];
    sprintf_s(chSize, 256, "%d", sumsize);
    SetDlgItemText(hWnd, ID_ES, chSize);
    UpdateWindow(hWnd);
    ReleaseMutex(hMutex);
    // Выход из программы
    return(0);
}

Полный код

        // --- Обязательный включаемый файл
    #include <cstdlib>
    #include <iostream>
    #include <windows.h>
    #define ID_EM 3000
    #define ID_ES 3001
    #define ID_BS 3002
    #define ID_BR 3003
    #define ID_BP 3004
    using namespace std;
    typedef struct
    {
        HWND hWnd;
        LPCTSTR lpszFileName;
        BOOL bInnerFolders;
    } MsParams_t;
    typedef struct
    {
        HWND hWnd;
        LPCTSTR file;
    } MsParams_t1;
    static MsParams_t1 params;
    // --- Описание функции главного окна
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
    // --- Глобальные переменные
    HINSTANCE hInst;        // Дескриптор экземпляра приложения
    char ClassName[] = "Window";        // Название класса окна
    char AppTitle[] = "";   // Заголовок главного окна
    DWORD sumsize = 0;
    HANDLE hThr;
    HANDLE thread;
    TCHAR buf[512];
    HANDLE hMutex = CreateMutex(NULL, FALSE, "mymutex");
    HANDLE hMutex1 = CreateMutex(NULL, FALSE, "mymutex1");
    DWORD WINAPI threadSize(void * param) {
        MsParams_t1 * ptr = (MsParams_t1 *)param;
        HWND hWnd = ptr->hWnd;
        LPCSTR file = ptr->file;
        ReleaseMutex(hMutex1);
        // Размер файла
        DWORD dwSize = 0;
        // Файл
        LPCTSTR lpszSystemInfo = file;
        // Открываем файл
        HANDLE hFile = CreateFile(lpszSystemInfo,
            GENERIC_READ,
            0,
            NULL,
            OPEN_EXISTING,
            FILE_FLAG_SEQUENTIAL_SCAN,
            NULL);
        if (hFile == INVALID_HANDLE_VALUE)
        {
            MessageBox(NULL, "Не удалось открыть файл",
                "Ошибка",
                MB_OK | MB_ICONEXCLAMATION);
        }
        // Получаем размер файла
        dwSize = GetFileSize(hFile, NULL);
        if (dwSize == INVALID_FILE_SIZE)
        {
            MessageBox(NULL, "Не удалось определить размер файла",
                "Ошибка",
                MB_OK | MB_ICONEXCLAMATION);
        }
        // Закрываем файл
        CloseHandle(hFile);
        hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mymutex");
        WaitForSingleObject(hMutex, INFINITE);
        sumsize += dwSize;
        char chSize[256];
        sprintf_s(chSize, 256, "%d", sumsize);
        SetDlgItemText(hWnd, ID_ES, chSize);
        UpdateWindow(hWnd);
        ReleaseMutex(hMutex);
        // Выход из программы
        return(0);
    }
    DWORD WINAPI file_seek(void * param)
    {
        MsParams_t * ptr = (MsParams_t *)param;
        HWND hWnd = ptr->hWnd;
        LPCTSTR lpszFileName = ptr->lpszFileName;
        BOOL bInnerFolders = ptr->bInnerFolders;
        LPTSTR part;
        char tmp[MAX_PATH]; // temporary array
        char name[MAX_PATH];
        char file[MAX_PATH];
        HANDLE hSearch = NULL;
        WIN32_FIND_DATA wfd;
        memset(&wfd, 0, sizeof(WIN32_FIND_DATA));
        //search in embeded folders for first
        if (bInnerFolders)
        {
            if (GetFullPathName(lpszFileName, MAX_PATH, tmp, &part) == 0)
                return FALSE;
            lstrcpy(name, part);
            lstrcpy(part, "*.*");
            //if folder exists, down to it
            wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
            if (!((hSearch = FindFirstFile(tmp, &wfd)) == INVALID_HANDLE_VALUE))
                do
                {
                    //if current folder is a service folders? which no need to check
                    if (!strncmp(wfd.cFileName, ".", 1) || !strncmp(wfd.cFileName, "..", 2))
                        continue;
                    if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) //if it's a folder
                    {
                        // making a new path
                        char next[MAX_PATH];
                        if (GetFullPathName(lpszFileName, MAX_PATH, next, &part) == 0)
                            return FALSE;
                        lstrcpy(part, wfd.cFileName);
                        lstrcat(next, "\\");
                        //cout << next << endl; 
                        lstrcat(next, name);
                    }
                } while (FindNextFile(hSearch, &wfd)); //finding next file in folder
                                                       //---------------------------------------------------------------------
                FindClose(hSearch); // closing a search descriptor
        }
        if ((hSearch = FindFirstFile(lpszFileName, &wfd)) == INVALID_HANDLE_VALUE)
            return TRUE;

        do
            if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) // is it's a file
            {
                if (GetFullPathName(lpszFileName, MAX_PATH, file, &part) == 0)
                    return FALSE;
                lstrcpy(part, wfd.cFileName);
                //******************************************
                hMutex1 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mymutex1");
                WaitForSingleObject(hMutex1, INFINITE);         
                params.hWnd = hWnd;
                params.file = (LPCTSTR)file;
                thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadSize, (void*)&params, 0, NULL);
                //WaitForSingleObject(thread, INFINITE);
                //******************************************
            }
        while (FindNextFile(hSearch, &wfd)); // next file in folder
        FindClose(hSearch); // close search descriptor
        char chSize[256];
        sprintf_s(chSize, 256, "%d", sumsize);
        SetDlgItemText(hWnd, ID_ES, chSize);
        UpdateWindow(hWnd);
        return TRUE;
    }
    // --- Функция WinMain
    int WINAPI WinMain(HINSTANCE hInstance,
        // Дескриптор экземпляра приложения
        HINSTANCE hPrevInstance, // В Win32 всегда равен NULL
        LPSTR lpCmdLine,
        // Указатель на командную строку. Он // позволяет
        // приложению получать данные из командной строки.
        int nCmdShow
        // Определяет, как приложение первоначально 
        // отображается на дисплее: пиктограммой
        // (nCmdShow = SW_SHOWMINNOACTIVE) 
        // или в виде открытого окна                    //(nCmdShow = SW_SHOWNORMAL).
    )
    {
        WNDCLASS wc;    // Структура для информации о классе окна
        HWND hWnd;  // Дескриптор главного окна приложения
        MSG msg;    // Структура для хранения сообщения
                    // Сохраняем дескриптор экземпляра приложения в глобальной
                    // переменной, чтобы при необходимости воспользоваться им в
                    // функции окна.
        hInst = hInstance;
        // --- Проверяем, было ли приложение запущено ранее.
        // Воспользуемся функцией FindWindow, которая позволяет
        // найти окно верхнего 
        // уровня по имени класса или по заголовку окна:
        // HWND FindWindow(LPCTSTR lpClassName,
        // LPCTSTRlpWindowName);
        // Через параметр lpClassName передается указатель на
        // текстовую строку, в которую необходимо записать имя
        // класса искомого окна. На базе одного и того же класса 
        // можно создать несколько окон. Если необходимо найти 
        // окно с заданным заголовком, то имя заголовка следует
        // передать через параметр lpWindowName. Если же подойдет 
        // любое окно, то параметр lpWindowName может иметь
        // значение NULL.
        if ((hWnd = FindWindow(ClassName, NULL)) != NULL)
        {
            // Пользователь может не помнить, какие приложения уже
            // запущены, а какие нет. Когда он запускает приложение, 
            // то ожидает, что на экране появится его главное окно.
            // Поэтому, если приложение было запущено ранее,
            // целесообразно активизировать и выдвинуть на передний
            // план его главное окно. Это именно то, к чему приготовился
            // пользователь.
            if (IsIconic(hWnd)) ShowWindow(hWnd, SW_RESTORE);
            SetForegroundWindow(hWnd);
            // Найдена работающая копия - работа новой копии
            // прекращается.
            return FALSE;
        }
        // --- Работающая копия не найдена - функция WinMain
        // приступает к инициализации. Заполнение структуры
        // WNDCLASS для регистрации класса окна.
        memset(&wc, 0, sizeof(wc));
        wc.lpszClassName = ClassName;       // Имя класса окон
        wc.lpfnWndProc = (WNDPROC)WndProc;
        // Адрес оконной функции
        wc.style = CS_HREDRAW | CS_VREDRAW; // Стиль класса 
        wc.hInstance = hInstance;       // Экземпляр приложения
        wc.hIcon = NULL;
        // Пиктограмма для окон
        wc.hCursor = NULL;
        // Курсор мыши для окон
        wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        // Кисть для окон
        wc.lpszMenuName = NULL;         // Ресурс меню окон
        wc.cbClsExtra = 0;          // Дополнительная память
        wc.cbWndExtra = 0;          // Дополнительная память
                                    // Pегистрация класса окна.
        RegisterClass(&wc);
        // Создаем главное окно приложения.
        hWnd = CreateWindow(
            ClassName,          // Имя класса окон
            AppTitle,           // Заголовок окна 
            WS_OVERLAPPEDWINDOW,        // Стиль окна
            CW_USEDEFAULT,          // X-координаты 
            CW_USEDEFAULT,          // Y-координаты 
            CW_USEDEFAULT,          // Ширина окна
            CW_USEDEFAULT,          // Высота окна
            NULL,           // Дескриптор окна-родителя
            NULL,           // Дескриптор меню окна
            hInst,      // Дескриптор экземпляра приложения
            NULL);      // Дополнительная информация
        if (!hWnd)
        {
            // Окно не создано, выдаем предупреждение.
            MessageBox(NULL,
                "Create: error", AppTitle, MB_OK | MB_ICONSTOP);
            return FALSE;
        }
        HWND hEditMask = CreateWindow("EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL
            , 10, 40, 150, 20, hWnd, (HMENU)ID_EM, hInstance, NULL);
        char buf1[50] = { "F:\\TestProg\\*.txt" };
        SetDlgItemText(hWnd, ID_EM, buf1);
        HWND hEditSize = CreateWindow("EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL
            , 10, 80, 150, 20, hWnd, (HMENU)ID_ES, hInstance, NULL);
        HWND hButtonStart = CreateWindow((LPCSTR)"button", (LPCSTR)"Search", WS_CHILD | WS_VISIBLE,
            180, 35, 100, 27, hWnd, (HMENU)ID_BS, 0, NULL);
        HWND hButtonResume = CreateWindow((LPCSTR)"button", (LPCSTR)"Resume", WS_CHILD | WS_VISIBLE,
            180, 65, 100, 27, hWnd, (HMENU)ID_BR, 0, NULL);
        HWND hButtonPause = CreateWindow((LPCSTR)"button", (LPCSTR)"Pause", WS_CHILD | WS_VISIBLE,
            180, 95, 100, 27, hWnd, (HMENU)ID_BP, 0, NULL);
        // Отображаем окно.
        ShowWindow(hWnd, nCmdShow);
        // Обновляем содержимое клиентской области окна.
        UpdateWindow(hWnd);
        // Запускаем цикл обработки очереди сообщений.
        // Функция GetMessage получает сообщение из очереди, 
        // выдает false при выборке из очереди сообщения WM_QUIT
        while (GetMessage(&msg, NULL, 0, 0))
        {
            // Преобразование некоторых сообщений, 
            // полученных с помощью клавиатуры
            TranslateMessage(&msg);
            // Отправляем сообщение оконной процедуре
            DispatchMessage(&msg);
        }
        return msg.wParam;
    }
    // --- Функция окна
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        char *str = (char *)"First Windows aplication";
        switch (msg)
        {
        case WM_COMMAND:
        {
            switch (LOWORD(wParam))
            {
            case ID_BS:
            {
                static MsParams_t params;
                sumsize = 0;
                params.hWnd = hWnd;
                params.bInnerFolders = true;
                SetDlgItemText(hWnd, ID_ES, "");
                GetDlgItemText(hWnd, ID_EM, buf, 512);
                params.lpszFileName = (LPCTSTR)buf;
                hThr = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)file_seek, (void*)&params, 0, NULL);
            }; break;
            case ID_BR:
            {
                ResumeThread(hThr);
            }; break;
            case ID_BP:
            {
                SuspendThread(hThr);
            }; break;
            }
        }; break;
        case WM_PAINT:
        {
            HDC hDC;
            PAINTSTRUCT ps;
            InvalidateRect(hWnd, NULL, TRUE);
            hDC = BeginPaint(hWnd, &ps);
            // Получить контекст окна
            // Рисование узора
            EndPaint(hWnd, &ps);
            // Освободить контекст окна
        }; break;
        case WM_DESTROY:
        {
            // Если данная функция является оконной функцией
            // главного окна, то следует в очередь сообщений
            // приложения послать сообщение WM_QUIT 
            PostQuitMessage(0);
        }; break;
        // Необработанные сообщения передаем в стандартную
        // функцию обработки сообщений по умолчанию.
        default: return DefWindowProc(hWnd, msg, wParam, lParam);
        }
        return 0l;
    }
READ ALSO
Алгоритм выхода из лабиринта

Алгоритм выхода из лабиринта

Нужно написать программу, которая находит самый быстрый путь из одной точки к другойЕсть массив, заполненный рандомно 0 и 1

231
Отображение километража по треку из GPX

Отображение километража по треку из GPX

Загружаю на карту файл GPX записанного трека (пройденного пути):

225
Данные Child в Parent undefined

Данные Child в Parent undefined

Пытаюсь извлечь данные из компонента ColorChild при помощи функции setNewColor которую передаю в props

238