Всем привет! Пишу программу, которая в первом поток ищет файлы, соответствующие маске, для каждого потока создает вторичный поток, в котором подсчитывается вес файла, суммируется с остальными и выводится на экран. Проблема в том, что переменная файл постоянно перезаписывается и в случае с 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*)¶ms, 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*)¶ms, 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*)¶ms, 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;
}
Оборудование для ресторана: новинки профессиональной кухонной техники
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
Нужно написать программу, которая находит самый быстрый путь из одной точки к другойЕсть массив, заполненный рандомно 0 и 1
Загружаю на карту файл GPX записанного трека (пройденного пути):
Пытаюсь извлечь данные из компонента ColorChild при помощи функции setNewColor которую передаю в props