Приложение для поиска файлов с несколькими потоками с использованием событий и критических разделов не работают, как и оC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Приложение для поиска файлов с несколькими потоками с использованием событий и критических разделов не работают, как и о

Сообщение Anonymous »

Я создал этот многополосный поиск файлов с использованием событий и критических разделов, а также у меня есть один поток (папка), чтобы найти все папки рекурсивно, и несколько потоков (FileThread) для поиска файлов в каждой из обнаруженных папок (я присваивал одну потоку для обнаружения папки, чтобы найти файлы для File Secupter Spearder), которые можно найти в номинации). В обнаруженных путях файлов я установил критические разделы для предотвращения условий и событий, чтобы уведомить спальные потоки для бодрствования и выполнения необходимых задач при пробуждении., но он не будет работать, как и ожидалось, что есть 2 файла, которые я хочу найти (оба с одинаковым именем: my_search_item.txt), один на этом пути d: \ search D: \ search \ test \ my_search_item.txt (что он выбирает дважды), любые идеи о том, как я могу это исправить.

Код: Выделить всё

#include 
#include 
#include  // For malloc, realloc, free
#include 
#include  // For wcslen and wcscpy

HANDLE hNewFileItemEvent;
HANDLE hNewSearchItemEvent;
HANDLE hNoMoreWorkEvent;
WCHAR* filePath;
WIN32_FIND_DATAW fd;
WCHAR subPath[MAX_PATH];
const WCHAR* rootPath = L"D:\\search";
CRITICAL_SECTION g_queueCS;

typedef struct {
WCHAR** data;      // Pointer to an array of string pointers
int size;         // Current number of strings in the array
int capacity;     // Allocated capacity of the array
} StringDynamicArray;

StringDynamicArray myFolders;

StringDynamicArray myFiles;

void initStringDynamicArray(StringDynamicArray* arr, int initialCapacity) {
arr->data = (WCHAR**)malloc(sizeof(WCHAR*) * initialCapacity);
if (arr->data == NULL) {
perror("Failed to allocate initial memory for string array");
exit(EXIT_FAILURE);
}
arr->size = 0;
arr->capacity = initialCapacity;
}

void pushString(StringDynamicArray* arr, const WCHAR* str) {
if (arr->size == arr->capacity) {
arr->capacity *= 2;
arr->data = (WCHAR**)realloc(arr->data, sizeof(WCHAR*) * arr->capacity);
if (arr->data == NULL) {
perror("Failed to reallocate memory for string array");
exit(EXIT_FAILURE);
}
}

size_t strLen = wcslen(str);
arr->data[arr->size] = (WCHAR*)malloc((strLen + 1) * sizeof(wchar_t)); // +1 for null terminator
if (arr->data[arr->size] == NULL) {
perror("Failed to allocate memory for string");
exit(EXIT_FAILURE);
}

// Use wcscpy_s with the correct buffer size (strLen + 1)
errno_t err = wcscpy_s(arr->data[arr->size], strLen + 1, str);
if (err == 0) {
wprintf(L"Successfully copied: %ls\n", arr->data[arr->size]);
arr->size++;
}
else {
wprintf(L"Error copying string.  Error code: %d\n", err);
}
}

WCHAR* popString(StringDynamicArray* arr) {
if (arr->size == 0) {
fprintf(stderr, "Error: Cannot pop from an empty array.\n");
return NULL;
}
arr->size--;
WCHAR* poppedStr = arr->data[arr->size];
return poppedStr; // Caller is responsible for freeing this memory
}

void freeStringDynamicArray(StringDynamicArray* arr) {
for (int i = 0; i < arr->size; i++) {
free(arr->data[i]); // Free individual strings
}
free(arr->data); // Free the array of pointers
arr->data = NULL;
arr->size = 0;
arr->capacity = 0;
}

void searchDirectories(const WCHAR* path) {
WIN32_FIND_DATAW findData;
HANDLE hFind = INVALID_HANDLE_VALUE;
WCHAR searchPath[MAX_PATH];
WCHAR subPath[MAX_PATH];

// Construct the search pattern (e.g., "D:\\search\\*")
swprintf_s(searchPath, MAX_PATH, L"%s\\*", path);

// Start the search with FindFirstFileW
hFind = FindFirstFileW(searchPath, &findData);
if (hFind == INVALID_HANDLE_VALUE) {
wprintf(L"Error opening directory %s: %d\n", path, GetLastError());
return;
}

// Iterate through all files and directories
do {
// Skip the current (".") and parent ("..") directories
if (wcscmp(findData.cFileName, L".") == 0 || wcscmp(findData.cFileName, L"..") == 0) {
continue;
}

// Construct the full path of the current file or directory
swprintf_s(subPath, MAX_PATH, L"%s\\%s", path, findData.cFileName);

// Print the full path
wprintf(L"%s\n", subPath);

// If it's a directory, recursively search it
if (findData.dwFileAttributes &  FILE_ATTRIBUTE_DIRECTORY) {
pushString(&myFolders, (LPCWSTR)subPath);
searchDirectories(subPath);
}

} while (FindNextFileW(hFind, &findData) != 0);

// Check if the loop ended due to an error
DWORD error = GetLastError();
if (error != ERROR_NO_MORE_FILES) {
wprintf(L"Error during directory search: %d\n", error);
}

// Close the search handle
FindClose(hFind);
}

//IN each directory provided as an argument search for all files in it
void searchFiles(const WCHAR* path) {
WIN32_FIND_DATAW findData;
HANDLE hFind = INVALID_HANDLE_VALUE;
WCHAR searchPath[MAX_PATH];
WCHAR subPath[MAX_PATH];

swprintf_s(searchPath, MAX_PATH, L"%s\\*", path);

// Start the search with FindFirstFileW
hFind = FindFirstFileW(searchPath, &findData);
if (hFind == INVALID_HANDLE_VALUE) {
wprintf(L"Error opening directory %s: %d\n", path, GetLastError());
return;
}

// Iterate through all files and directories
do {
// Skip the current (".") and parent ("..") directories
if (wcscmp(findData.cFileName, L".") == 0 || wcscmp(findData.cFileName, L"..") == 0) {
continue;
}

// Construct the full path of the current file or directory
swprintf_s(subPath, MAX_PATH, L"%s\\%s", path, findData.cFileName);

// Print the full path
wprintf(L"%s\n", subPath);

// If it's NOT a directory, write it to the myFiles Struct
if (findData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) {
::EnterCriticalSection(&g_queueCS);
printf("Size: %d\n", myFiles.size);
pushString(&myFiles, (LPCWSTR)subPath);
::LeaveCriticalSection(&g_queueCS);
::SetEvent(hNewSearchItemEvent);
}

} while (FindNextFileW(hFind, &findData) != 0);

// Check if the loop ended due to an error
DWORD error = GetLastError();
if (error != ERROR_NO_MORE_FILES) {
wprintf(L"Error during directory search: %d\n", error);
}

// Close the search handle
FindClose(hFind);
}

BOOL FileMatchesSearch(WCHAR fullPath[], WCHAR targetString[]) {

size_t fullPathLen = wcslen(fullPath);
size_t targetStringLen = wcslen(targetString);

// Check if the full path is long enough to contain the target string
if (fullPathLen >= targetStringLen) {
// Get a pointer to the potential start of the target string in fullPath
WCHAR* endOfPath = fullPath + (fullPathLen - targetStringLen);

// Compare the substring with the target string
if (wcscmp(endOfPath, targetString) == 0) {
//printf("'%ws' exists at the end of the path.\n", targetString);
printf("File path found: %ws\n", fullPath);
return TRUE;
}
else {
printf("'%ws' does NOT exist at the end of the path.\n", targetString);
return FALSE;
}
}
else {
printf("The path is too short to contain '%ws'.\n", targetString);
return FALSE;
}
}

DWORD WINAPI FolderThread(PVOID) {
searchDirectories(rootPath);
::SetEvent(hNewFileItemEvent);
return 42;
}

DWORD WINAPI FileThread(LPVOID lpParam) {
const WCHAR* folderPath = (WCHAR*)lpParam;
wprintf(L"Processing string: %s\n", folderPath);

while (true) {
HANDLE waitHandles[2] = { hNewFileItemEvent, hNoMoreWorkEvent };
DWORD waitResult = WaitForMultipleObjects(2, waitHandles, FALSE, INFINITE);

if (waitResult == WAIT_OBJECT_0 + 1) { // hNoMoreWorkEvent is signaled
return 0; // Exit the thread
}
else {
break;
}
}

searchFiles(folderPath);

return 42;
}

DWORD WINAPI SearchThread(PVOID) {

while (true) {
HANDLE waitHandles[2] = { hNewSearchItemEvent, hNoMoreWorkEvent };
DWORD waitResult = WaitForMultipleObjects(2, waitHandles, FALSE, INFINITE);

if (waitResult == WAIT_OBJECT_0 + 1) { // hNoMoreWorkEvent is signaled
break;  // Exit the thread
}

// Else, hNewItemEvent was signaled. Grab work.
//Sleep(10000);
::EnterCriticalSection(&g_queueCS);

if (myFiles.size != 0) {
filePath = popString(&myFiles);

// If we just took the last item, reset the event

}
else if (myFiles.size == 0) {
::ResetEvent(hNewSearchItemEvent);
}
::LeaveCriticalSection(&g_queueCS);

WCHAR searchPattern[] = L"My_search_item.txt";

// Allocate a WCHAR array on the stack, including space for the null terminator
const int MAX_LENGTH = 256; // Or a suitable maximum length
WCHAR destinationArray[MAX_LENGTH];

// Copy the string
wcscpy_s(destinationArray, MAX_LENGTH, filePath);
if (FileMatchesSearch(destinationArray, searchPattern)) {
printf("File Found...!!!\n");

}
}
return 0;
}

int main()
{
::InitializeCriticalSection(&g_queueCS);
initStringDynamicArray(&myFolders, 5);
initStringDynamicArray(&myFiles, 5);

// Create a manual-reset event in a non-signaled state
hNewFileItemEvent = ::CreateEvent(
NULL,               // Default security attributes
TRUE,               // Manual-reset event
FALSE,              // Initial state is non-signaled
L"NewItemEvent" // Name of the event (optional)
);

// Create a manual-reset event in a non-signaled state
hNewSearchItemEvent = ::CreateEvent(
NULL,               // Default security attributes
TRUE,               // Manual-reset event
FALSE,              // Initial state is non-signaled
L"NewItemEvent" // Name of the event (optional)
);

// Create a manual-reset event in a non-signaled state
hNoMoreWorkEvent = ::CreateEvent(
NULL,               // Default security attributes
TRUE,               // Manual-reset event
FALSE,              // Initial state is non-signaled
L"NewItemEvent" // Name of the event (optional)
);

//************************Folder thread
HANDLE hThreadFolder = ::CreateThread(NULL,0, FolderThread, NULL, 0 ,NULL);
::WaitForSingleObject(hThreadFolder, INFINITE);

// Array to store thread handles
HANDLE* threads = (HANDLE*)malloc(myFolders.size * sizeof(HANDLE));
if (!threads) {
wprintf(L"Failed to allocate memory for thread handles\n");
return 1;
}

//**************MULtiple threads to look for files in each folder discovered (One thread per folder)
// Loop through the data array and create a thread for each index
for (int i = 0; i < myFolders.size; i++) {
threads[i] = CreateThread(
NULL,                   // Default security attributes
0,                     // Default stack size
FileThread,        // Thread function
myFolders.data[i],     // Pass the string at index i
0,                     // Default creation flags
NULL                   // No thread ID needed
);

if (threads[i] == NULL) {
wprintf(L"Failed to create thread for index %d\n", i);
// Handle error (e.g., clean up and exit)
}
}

// Wait for all threads to complete
WaitForMultipleObjects(myFolders.size, threads, TRUE, INFINITE);

// ****************************Singe thread to Search for the File by file name
HANDLE hThreadSearch = ::CreateThread(NULL, 0, SearchThread, NULL, 0, NULL);
::WaitForSingleObject(hThreadSearch, INFINITE);

// Clean up thread handles
for (int i = 0; i < myFolders.size; i++) {
if (threads[i]) {
CloseHandle(threads[i]);
}
}

// Clean up allocated memory
for (int i = 0; i < myFolders.size; i++) {
free(myFolders.data[i]); // Free each string
}
free(myFolders.data); // Free the array of pointers
free(threads); // Free thread handles array
::CloseHandle(hThreadFolder);
::CloseHandle(hThreadSearch);

::DeleteCriticalSection(&g_queueCS);

freeStringDynamicArray(&myFolders);
freeStringDynamicArray(&myFiles);

return 0;
}
вывод терминала

Подробнее здесь: https://stackoverflow.com/questions/797 ... working-as
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»