I am studying the Thread Ordering Service of Windows. So, I have written the following code to test how TOS works really? But it doesn't work and it gives me an error.
#include <windows.h>
#include <process.h>
#include <iostream>
#include <avrt.h>
#include <stdio.h>
#pragma comment(lib, "Avrt.lib")
#define _100NS_IN_1MS 10000
unsigned __stdcall Thread1(void* arg_list)
{
for (size_t i = 0; i < 100; i++)
{
std::cout << "\tHello from Thread1, Repeat #" << i + 1 << std::endl;
SwitchToThread();
}
return 0;
}
unsigned __stdcall Thread2(void* arg_list)
{
for (size_t i = 0; i < 100; i++)
{
std::cout << "\tHello from Thread2, Repeat #" << i + 1 << std::endl;
}
return 0;
}
int main()
{
HANDLE handle_context = NULL;
LARGE_INTEGER period, timeout;
GUID guid = { 0 };
BOOL result;
period.QuadPart = Int32x32To64(_100NS_IN_1MS, 1000); // 1 second
timeout.QuadPart = Int32x32To64(_100NS_IN_1MS, 10000); // 10 seconds
result = AvRtCreateThreadOrderingGroup(&handle_context, &period, &guid, &timeout);
if (result != TRUE)
{
printf("Error creating group (%d)\n", GetLastError());
return 1;
}
HANDLE handle_thread1 = (HANDLE)_beginthreadex(NULL, 0, Thread1, NULL, CREATE_SUSPENDED, NULL);
HANDLE handle_thread2 = (HANDLE)_beginthreadex(NULL, 0, Thread2, NULL, CREATE_SUSPENDED, NULL);
AvRtJoinThreadOrderingGroup(&handle_thread1, &guid, FALSE);
AvRtJoinThreadOrderingGroup(&handle_thread2, &guid, FALSE);
if (handle_thread1 == NULL && handle_thread2 == NULL)
{
return -1;
}
ResumeThread(handle_thread1);
ResumeThread(handle_thread2);
int recieve1 = WaitForSingleObject(handle_thread1, INFINITE);
int recieve2 = WaitForSingleObject(handle_thread2, INFINITE);
CloseHandle(handle_thread1);
CloseHandle(handle_thread2);
}
When I run the above program, it gives me the following error:
Error creating group (1058)
1058 (0x422)
The service cannot be started, either because it is disabled or
because it has no enabled devices associated with it.
What should I do now? I am using Windows 10.
The links here and here, explain that Windows Thread Ordering Service is not on by default:
The thread ordering service is off by default and must be started by
the user. While the thread ordering service is running, it is
activated every 5 seconds to check whether there is a new request,
even if the system is idle. This prevents the system from sleeping for
longer than 5 seconds, causing the system to consume more power. If
energy efficiency is critical to the application, it is better not to
use the thread ordering service and instead allow the system scheduler
to manage execution of threads.
Use cases and other discussion are also discussed and code snippets are provided in some of the other links (see 2nd link above.) Following is an example:
#include <windows.h>
#include <avrt.h>
#include <stdio.h>
#pragma comment(lib, "Avrt.lib")
#define _100NS_IN_1MS 10000
int main( void )
{
HANDLE hContext = NULL;
LARGE_INTEGER period, timeout;
GUID guid = { 0 };
BOOL bRes;
period.QuadPart = Int32x32To64(_100NS_IN_1MS, 1000); // 1 second
timeout.QuadPart = Int32x32To64(_100NS_IN_1MS, 10000); // 10 seconds
bRes = AvRtCreateThreadOrderingGroup(
&hContext,
&period,
&guid,
&timeout );
if( bRes != TRUE )
{
printf("Error creating group (%d)\n", GetLastError());
return 1;
}
return 0;
}
Related
In Win32 C++, How to WaitForSingleObject and Detect Ctrl-C at the same time?
I tried the following console application by compiling it in the Code::Blocks C++ compiler for windows.
Then, I tried pressing Control-C many times while running... it basically doesn't call the control-c handler while the main thread is in "WaitForSingleObject".
Is there a way to fix this?
Eventually, I want my Control-C handler to kill the secondary thread using TerminateThread and return control to mainthread breaking WaitForSingleObject... But, because of the wait the second thread is written i can't change any of the code...
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <atomic>
using namespace std;
BOOL WINAPI fun1(DWORD id);
DWORD WINAPI fun2(void*);
atomic<DWORD> threadid {0};
int main()
{
DWORD threadid1;
cout << "Hello world!" << endl;
SetConsoleCtrlHandler(fun1, TRUE);
HANDLE H1 = CreateThread(NULL, 0, fun2, 0, 0, &threadid1);
threadid = threadid1;
WaitForSingleObject(H1, INFINITE);
return 0;
}
BOOL WINAPI fun1(DWORD id)
{
Beep(750, 300);
printf("CtrlHandler:(%ld)\n", id);
if (threadid != 0) {
HANDLE H2 = OpenThread(THREAD_TERMINATE, FALSE, threadid);
if (H2) {
//TerminateThread(H2, 0);
//threadid = 0;
CloseHandle(H2);
}
}
return TRUE;
}
DWORD WINAPI fun2(void*)
{
// This thread will eventually do some work...
// and I don't want to rewrite this code...
// to check for a flag from another thread...
int count = 0;
while(1) {
printf("count: %d\n", count);
Sleep(1000);
}
return 0;
}
A SetConsoleCtrlHandler() handler gets run by the OS in its own thread. This is stated as much in the documentation:
https://learn.microsoft.com/en-us/windows/console/handlerroutine
An application-defined function used with the SetConsoleCtrlHandler function. A console process uses this function to handle control signals received by the process. When the signal is received, the system creates a new thread in the process to execute the function.
You need to have that signal thread notify your worker thread to terminate itself, you can't (safely) just terminate the thread directly (ie, DO NOT use TerminateThread()).
Try this:
#include <windows.h>
#include <cstdio>
#include <iostream>
#include <atomic>
using namespace std;
BOOL WINAPI fun1(DWORD);
DWORD WINAPI fun2(void*);
atomic<bool> exitThread {false};
int main()
{
cout << "Hello world!" << endl;
SetConsoleCtrlHandler(fun1, TRUE);
HANDLE H1 = CreateThread(NULL, 0, fun2, 0, 0, NULL);
if (H1)
{
WaitForSingleObject(H1, INFINITE);
CloseHandle(H1);
}
return 0;
}
BOOL WINAPI fun1(DWORD id)
{
Beep(750, 300);
printf("CtrlHandler:(%lu)\n", id);
exitThread = true;
return TRUE;
}
DWORD WINAPI fun2(void*)
{
// This thread will eventually do some work...
int count = 0;
while (!static_cast<bool>(exitThread)) {
printf("count: %d\n", count++);
Sleep(1000);
}
return 0;
}
However, do note that creating a thread just to wait on it is a waste of a thread. You may as well just do your work in main() directly instead, eg:
#include <windows.h>
#include <cstdio>
#include <iostream>
#include <atomic>
using namespace std;
BOOL WINAPI fun1(DWORD);
atomic<bool> exitApp {false};
int main()
{
cout << "Hello world!" << endl;
SetConsoleCtrlHandler(fun1, TRUE);
// This will eventually do some work...
int count = 0;
while (!static_cast<bool>(exitApp)) {
printf("count: %d\n", count++);
Sleep(1000);
}
return 0;
}
BOOL WINAPI fun1(DWORD id)
{
Beep(750, 300);
printf("CtrlHandler:(%lu)\n", id);
exitApp = true;
return TRUE;
}
I cleaned up your code slightly and it seems like the Ctrl+C handler is running when expected (even though it doesn't do anything particularly useful). When I type Ctrl+C, I see that fun1 can run multiple times while the main thread is running WaitForSingleObject.
Your original code for fun1 was beeping before printing, and it wasn't flushing the stdout buffer, so maybe you thought the code wasn't actually running or that it was getting delayed.
Note that I am just answering questions you asked about detecting Ctrl+C while waiting for an object; I'm not attempting to help you do anything useful in your Ctrl+C handler.
Here is the cleaned-up version of your code that I used for testing:
#include <windows.h>
#include <stdio.h>
#include <atomic>
std::atomic<DWORD> threadid {0};
BOOL WINAPI fun1(DWORD id) {
printf("fun1: %ld\n", id);
fflush(stdout);
Beep(750, 100);
// This doesn't do anything useful; can be removed.
if (threadid != 0) {
HANDLE H2 = OpenThread(THREAD_TERMINATE, FALSE, threadid);
if (H2) { CloseHandle(H2); }
}
return 1;
}
DWORD WINAPI fun2(void *) {
unsigned int count = 0;
while(1) {
count++;
printf("count: %d\n", count);
fflush(stdout);
Sleep(4000);
}
return 0;
}
int main() {
printf("Hello world!\n");
fflush(stdout);
SetConsoleCtrlHandler(fun1, TRUE);
DWORD threadid1;
HANDLE H1 = CreateThread(NULL, 0, fun2, 0, 0, &threadid1);
threadid = threadid1;
printf("Waiting for single oblect.\n");
fflush(stdout);
WaitForSingleObject(H1, INFINITE);
printf("Done waiting for single oblect.\n");
fflush(stdout);
return 0;
}
Example output:
Hello world!
Waiting for single oblect.
count: 1
count: 2
fun1: 0
fun1: 0
fun1: 0
fun1: 0
fun1: 0
fun1: 0
fun1: 0
fun1: 0
fun1: 0
count: 3
count: 4
I compiled the code in MSYS2, targeting 64-bit Windows, with this command:
g++ -std=gnu++20 -Wall -Wextra test.cpp
I'm a beginner and I'm trying to reproduce a rae condition in order to familirize myself with the issue. In order to do that, I created the following program:
#include <Windows.h>
#include <iostream>
using namespace std;
#define numThreads 1000
DWORD __stdcall addOne(LPVOID pValue)
{
int* ipValue = (int*)pValue;
*ipValue += 1;
Sleep(5000ull);
*ipValue += 1;
return 0;
}
int main()
{
int value = 0;
HANDLE threads[numThreads];
for (int i = 0; i < numThreads; ++i)
{
threads[i] = CreateThread(NULL, 0, addOne, &value, 0, NULL);
}
WaitForMultipleObjects(numThreads, threads, true, INFINITE);
cout << "resulting value: " << value << endl;
return 0;
}
I added sleep inside a thread's function in order to reproduce the race condition as, how I understood, if I just add one as a workload, the race condition doesn't manifest itself: a thread is created, then it runs the workload and it happens to finish before the other thread which is created on the other iteration starts its workload. My problem is that Sleep() inside the workload seems to be ignored. I set the parameter to be 5sec and I expect the program to run at least 5 secs, but insted it finishes immediately. When I place Sleep(5000) inside main function, the program runs as expected (> 5 secs). Why is Sleep inside thread unction ignored?
But anyway, even if the Sleep() is ignored, the program outputs this everytime it is launched:
resulting value: 1000
while the correct answer should be 2000. Can you guess why is that happening?
WaitForMultipleObjects only allows waiting for up to MAXIMUM_WAIT_OBJECTS (which is currently 64) threads at a time. If you take that into account:
#include <Windows.h>
#include <iostream>
using namespace std;
#define numThreads MAXIMUM_WAIT_OBJECTS
DWORD __stdcall addOne(LPVOID pValue) {
int* ipValue=(int*)pValue;
*ipValue+=1;
Sleep(5000);
*ipValue+=1;
return 0;
}
int main() {
int value=0;
HANDLE threads[numThreads];
for (int i=0; i < numThreads; ++i) {
threads[i]=CreateThread(NULL, 0, addOne, &value, 0, NULL);
}
WaitForMultipleObjects(numThreads, threads, true, INFINITE);
cout<<"resulting value: "<<value<<endl;
return 0;
}
...things work much more as you'd expect. Whether you'll actually see results from the race condition is, of course, a rather different story--but on multiple runs, I do see slight variations in the resulting value (e.g., a low of around 125).
Jerry Coffin has the right answer, but just to save you typing:
#include <Windows.h>
#include <iostream>
#include <assert.h>
using namespace std;
#define numThreads 1000
DWORD __stdcall addOne(LPVOID pValue)
{
int* ipValue = (int*)pValue;
*ipValue += 1;
Sleep(5000);
*ipValue += 1;
return 0;
}
int main()
{
int value = 0;
HANDLE threads[numThreads];
for (int i = 0; i < numThreads; ++i)
{
threads[i] = CreateThread(NULL, 0, addOne, &value, 0, NULL);
}
DWORD Status = WaitForMultipleObjects(numThreads, threads, true, INFINITE);
assert(Status != WAIT_FAILED);
cout << "resulting value: " << value << endl;
return 0;
}
When things go wrong, make sure you've asserted the return value of any Windows API function that can fail. If you really badly need to wait on lots of threads, it is possible to overcome the 64-thread limit by chaining. I.e., for every additional 64 threads you need to wait on, you sacrifice a thread whose sole purpose is to wait on 64 other threads, and so on. We (Windows Developer's Journal) published an article demonstrating the technique years ago, but I can't recall the author name off the top of my head.
I'm trying to make a simple client-server program using windows file mapping and that uses semaphores. The clients send to the server 2 numbers, the server computes nr1+nr2 and nr1 * nr2. I tried something but it doesn't even work for 1 client and I want it to work for more clients. Here's the code:
the server:
#include <windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;
typedef struct {
int nr1;
int nr2;
} Mesaj;
int main(int argc, char** argv) {
Mesaj* mesaj;
HANDLE createSemaphore = CreateSemaphore(NULL, 1, 1, "Semafor");
if (createSemaphore == NULL || createSemaphore == INVALID_HANDLE_VALUE) {
wcout << "Failed to create a semaphore\n";
} else {
wcout << "Created the semaphore\n";
}
HANDLE hMemory = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE, 0, sizeof(Mesaj), "SharedMemory");
WaitForSingleObject(createSemaphore, INFINITE);
mesaj = (Mesaj*) MapViewOfFile(hMemory, FILE_MAP_READ, 0, 0, sizeof(Mesaj));
printf("The numbers received are: %d, %d\n", mesaj->nr1, mesaj->nr2);
int produs = mesaj->nr1 * mesaj->nr2;
int suma = mesaj->nr1 + mesaj->nr2;
printf("\nSuma numerelor este: %d iar produsul lor este: %d", suma, produs);
ReleaseSemaphore(createSemaphore, 1, NULL);
Sleep(INFINITE);
return 0;
}
the client:
#include <windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;
typedef struct {
int nr1;
int nr2;
} Mesaj;
int main(int argc, char** argv) {
Mesaj* mesaj, *mesaj2;
mesaj2 = (Mesaj*) malloc(sizeof(Mesaj));
HANDLE hMemory = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE,
"SharedMemory");
if (hMemory == NULL) {
wcout << "Error at OpenFileMapping\n";
}
HANDLE openSemaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS,TRUE,"Semafor");
if(openSemaphore != NULL || openSemaphore != INVALID_HANDLE_VALUE){
wcout<<"the semaphore is opened\n";
}
mesaj2 = (Mesaj*) MapViewOfFile(hMemory, FILE_MAP_WRITE, 0, 0,
sizeof(Mesaj));
int nr1 = 0, nr2 = 0;
printf("Give a number: ");
scanf("%d", &nr1);
printf("Give another number: ");
scanf("%d", &nr2);
mesaj2->nr1 = nr1;
mesaj2->nr2 = nr2;
if (mesaj2 == NULL) {
wcout << "Error\n"
} else {
wcout << "I sent " << mesaj2->nr1 << " and " << mesaj2->nr2 << endl;
}
system("pause");
return 0;
}
What exactly am I doing wrong? How should I work with semaphores?
When I open the server it doesn't wait for the client.
The documentation for CreateSemaphore says
The state of a semaphore object is signaled when its count is greater than zero, and nonsignaled when its count is equal to zero. The lInitialCount parameter specifies the initial count.
You passed lInitialCount=1 when you created the semaphore. and 1 > 0, so the semaphore is signaled and the WaitForSingleObject returns immediately.
You presumably want to create the semaphore with an initial count of 0, so that it does not become signaled until somebody calls ReleaseSemaphore.
I am writing to write a program that will make use of multithreading. I tried to read about multithreading and was able to get a sample program working. However I have run into a glitch and I am not sure what is going wrong. I am posting the sample program and will highlight where I am experiencing trouble.
#include <Windows.h>
#include <process.h>
#include <iostream>
#include <cassert>
#include <ctime>
#import "calc.dll" \
auto_rename no_namespace no_smart_pointers \
raw_native_types named_guids
using namespace std;
HANDLE th_mutex;
struct Arguments
{
string case_id;
string file;
};
//____________________________________
unsigned int __stdcall TestThread(void *args)
{
int i = 0,
j = 0;
cout << "Inside thread" << endl;
for (i = 0; i <= 10000; i++)
{
for (j = 0; j <= 100000; j++)
{
}
if (i == 10000)
cout << "The value of i inside the thread = " << i << endl;
}
return EXIT_SUCCESS;
}
//____________________________________
unsigned int __stdcall Thread(void *args)
{
CoInitialize(0);
{
Arguments *input;
input = (Arguments *) args;
time_t current_time;
time(¤t_time);
cout << ctime(¤t_time) << endl;
IHeatExchangerNetwork *hxNetwork = 0;
IDispatchPtr theUnit = 0;
IHeatTransferUnit *unit = 0;
VARIANT vAppend;
_bstr_t filename,
output;
filename = input->file.c_str();
filename += input->case_id.c_str();
filename += ".dat";
output = input->file.c_str();
output += input->case_id.c_str();
output += ".dbo";
cout << filename << endl;
cout << output << endl;
HRESULT hr = CoCreateInstance(CLSID_HeatExchangerNetwork,
0,
CLSCTX_ALL,
DIID_IHeatExchangerNetwork,
reinterpret_cast<void**>(&hxNetwork));
theUnit = hxNetwork->LoadHeatTransferUnit(filename, HxUnitTypeKey::HxUnitTypeCrossflow);
hr = theUnit->QueryInterface(DIID_IHeatTransferUnit, reinterpret_cast<void**>(&unit));
hxNetwork->Run(0, 0);
vAppend.boolVal = false;
unit->WriteDBOFile(output, OutputData, vAppend);
time(¤t_time);
cout << ctime(¤t_time) << endl;
}
CoUninitialize();
return EXIT_SUCCESS;
}
//____________________________________
int main()
{
DWORD retval;
Arguments args[2];
args[0].case_id = "1";
args[0].file = "C:\\Documents and Settings\\User\\My Documents\\Test Cases\\1\\";
args[1].case_id = "2";
args[1].file = "C:\\Documents and Settings\\User\\My Documents\\Test Cases\\2\\";
th_mutex = CreateMutex(NULL, FALSE, NULL);
if (th_mutex == NULL)
{
printf("CreateMutex error: %d\n", GetLastError());
return 1;
}
// ================================
// Basic testing of calling threads
// ================================
HANDLE hnd1;
cout << "Before creating new thread" << endl;
hnd1 = (HANDLE) _beginthreadex(NULL, 0, &TestThread, NULL, 0, 0);
cout << "After creating thread" << endl;
// ====================================
// Calling Calc routine through threads
// ====================================
HANDLE hnd2,
hnd3;
hnd2 = (HANDLE) _beginthreadex(NULL,
0,
&Thread,
(void *)&args[0],
0,
0);
hnd3 = (HANDLE) _beginthreadex(NULL,
0,
&Thread,
(void *)&args[1],
0,
0);
WaitForSingleObject(hnd1, INFINITE);
WaitForSingleObject(hnd2, INFINITE);
WaitForSingleObject(hnd3, INFINITE);
GetExitCodeThread(hnd1, &retval); // Gets the return value from the function
CloseHandle(hnd1);
CloseHandle(hnd2);
CloseHandle(hnd3);
return EXIT_SUCCESS;
}
The problem I am facing is when I execute the program I get the following output
Before creating new thread
After creating threadInside thread
Thu Aug 09 10:56:58 2012
Thu Aug 09 10:56:58 2012
C:\Documents and Settings\User\My Documents\Test Cases\1\1.datC:\Documents and Settings\User
\My Documents\Test Cases\2\2.dat
C:\Documents and Settings\kcomandur\My Documents\Test Cases\1\1.dboC:\Documents and Settings\User
\My Documents\Test Cases\2\2.dbo
The value of i inside the thread = 10000
Thu Aug 09 10:57:08 2012
and then program crashes. I get the following error
Debug Error!
Program: ...MultiThreading.exe
R6010
-abort() has been called
(Press Retry to debug the application)
When I do a retry, the break occurs in the generated .tli file in the following location starting with _com_dispatch_method
#pragma implementation_key(723)
inline IDispatch * IHeatExchangerNetwork::LoadHeatTransferUnit ( BSTR filename, enum HxUnitTypeKey unitType ) {
IDispatch * _result = 0;
_com_dispatch_method(this, 0x20, DISPATCH_METHOD, VT_DISPATCH, (void*)&_result,
L"\x0008\x0003", filename, unitType);
return _result;
}
The filename variable has the value
C:\Documents and Settings\User\My Documents\Test Cases\2\2.dat
I tried using mutex and modified the Thread function
unsigned int __stdcall Thread(void *args)
{
CoInitialize(0);
{
WaitForSingleObject(th_mutex, INFINITE);
// Same content as original Thread function.
// Not writing it again to minimize space
ReleaseMutex(th_mutex);
}
CoUninitialize();
return EXIT_SUCCESS;
}
//____________________________________
This time the program crashes at the following location _com_dispatch_method in the .tli file
#pragma implementation_key(966)
inline long IHeatTransferUnit::WriteDBOFile ( BSTR filename, short io, const VARIANT & vAppend ) {
long _result = 0;
_com_dispatch_method(this, 0x32, DISPATCH_METHOD, VT_I4, (void*)&_result,
L"\x0008\x0002\x080c", filename, io, &vAppend);
return _result;
}
By using mutex the error is being generated by the thread which has the HANDLE hnd3. The variable filename has the value
C:\Documents and Settings\User\My Documents\Test Cases\2\2.dbo
Also by using mutex I was able to get past the previous error location.
I am not sure if I really need a mutex as the following call
hxNetwork->Run(0, 0);
works on two different files that are no way related to each other. Also this is the most time consuming portion of the program and hence I wanted to run 2 cases simultaneously.
By using mutex the way I did, it runs the first case and then the second case.
Also the I have no control over the calc.dll. It is a third part software and I am not sure if supports multithreading or not.
So I would like to know what I need to do to get both the runs going and also be able to output the 2 files
Thanks in advance
I am trying to create files in a pen drive. If the pen drive is not present, threads should suspend. When it is inserted it should resume. Here is the code I tried but it's not working properly. Can any one help me?
#include "stdafx.h"
#include <Windows.h>
#include <Strsafe.h>
#include <WinBase.h>
LPCTSTR Disk=L"E:\";
LPTSTR drive_Name=L"E:\\demo";
CRITICAL_SECTION section;
#define BUFFER_SIZE 1024
#define count 10
HANDLE Write_Handle[10],Open_Handle[10],read_Handle[10] ;
DWORD WINAPI check_Thread(LPVOID lpParameter)
{
int *nThreadNo = (int*)lpParameter;
while(1)
{
if(GetDiskFreeSpaceExW(Disk,NULL,NULL,NULL))
{
ResumeThread(Write_Handle[*nThreadNo]);
ResumeThread(read_Handle[*nThreadNo]);
}
else
{
SuspendThread(Write_Handle[*nThreadNo]);
SuspendThread(read_Handle[*nThreadNo]);
}
}
}
DWORD WINAPI Write_Thread(LPVOID lpParameter)
{
DWORD g_tid = GetCurrentThreadId();
_tprintf(_T(" write thread id %d\n"),g_tid);
LPCWSTR filename=(LPCWSTR)lpParameter;
HANDLE ofile;
EnterCriticalSection(§ion);
ofile=CreateFileW(filename,GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_ALWAYS,NULL, NULL);
int d;
d=GetLastError();
if(ERROR_SUCCESS!=GetLastError())
{
_tprintf(_T("error values in open thread %d \n"),GetLastError());
_tprintf(_T("filename %s \n"),filename);
}
const int filesizeinKB = 1024;
BOOL bError;
DWORD dwBytesWritten=0;
WCHAR ReadBuffer[BUFFER_SIZE] = {0};
int i;
for(i = 0; i <= BUFFER_SIZE; i++)
{
ReadBuffer[i] = (char)(i%26 + 'a');
}
for (i = 0; i <= filesizeinKB; i++)
{
SetLastError(0);
bError= WriteFile(ofile, ReadBuffer-1, BUFFER_SIZE,&dwBytesWritten, NULL);
bError=GetLastError();
if (ERROR_SUCCESS!=GetLastError())
{ _tprintf(_T("error value in write %d\n"),GetLastError());
_tprintf(_T(" Write Error...\n"));
return 1;
}
}
SetLastError(0);
CloseHandle(ofile);
_tprintf(_T("write close error values %d\n"),GetLastError());
LeaveCriticalSection(§ion);
return 1;
}
DWORD WINAPI Read_Thread(LPVOID lpParameter)
{
HANDLE ofile;
DWORD g_tid = GetCurrentThreadId();
_tprintf(_T(" write thread id %d\n"),g_tid);
LPCWSTR filename=(LPCWSTR)lpParameter;
EnterCriticalSection(§ion);
ofile=CreateFileW(filename,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_ALWAYS,NULL, NULL);
int d;
d=GetLastError();
if(ERROR_SUCCESS!=GetLastError())
{
_tprintf(_T("error values in open thread %d \n"),GetLastError());
_tprintf(_T("filename %s \n"),filename);
}
DWORD dwBytesRead=0;
WCHAR ReadBuffer[BUFFER_SIZE] = {0};
_tprintf(_T(" read thread \n"));
SetLastError(0);
int err;
ReadFile(ofile, ReadBuffer, (BUFFER_SIZE-1), &dwBytesRead, NULL);
err=GetLastError();
_tprintf(_T("read error values %d \n"),GetLastError());
if(ERROR_SUCCESS!=GetLastError())
{
_tprintf(L"reading failed \n");
return 0;
}
SetLastError(0);
CloseHandle(ofile);
err=GetLastError();
_tprintf(_T("close error values %d\n"),GetLastError());
LeaveCriticalSection(§ion);
return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
unsigned int myCounter = 0;
DWORD WritethreadID,OpenThreadID,ReadthreadID;
HANDLE check_Handle;
DWORD exThread;
TCHAR filename[100];
HANDLE hfile;
INT bsize=100;
int i=0;
InitializeCriticalSection (§ion);
CreateDirectory(drive_Name,NULL);
for(i=0;i<5;i++)
{
SetLastError(0);
StringCchPrintf(filename,bsize, TEXT("%s\\file_%d.txt"),drive_Name,i );
hfile=CreateFileW(filename,GENERIC_WRITE|GENERIC_READ,NULL,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if (hfile == INVALID_HANDLE_VALUE)
{
_tprintf(_T("invalid handle \n" ));
}
_tprintf(_T("file created %s\n"),filename);
CloseHandle(hfile);
Write_Handle[i] =CreateThread(0, 0, Write_Thread, filename, CREATE_SUSPENDED, &WritethreadID);
SetThreadPriority(Write_Handle[i],2);
_tprintf(_T("write thread id is %d\n"),WritethreadID);
read_Handle[i]=CreateThread(0, 0, Read_Thread, filename, CREATE_SUSPENDED, &ReadthreadID);
SetThreadPriority(read_Handle[i],1);
_tprintf(_T("read thread id is %d\n "),ReadthreadID);
check_Handle =CreateThread(0, 0, check_Thread,(void*)&i ,0,&OpenThreadID);
}
for (i=0; i<count; ++i)
{
WaitForSingleObject(Write_Handle[i],INFINITE);
if ( !GetExitCodeThread(Write_Handle, &exThread) )
{
_tprintf(_T("close thread %08X\n"),GetLastError());
}
SetLastError(0);
CloseHandle(Write_Handle[i]);
_tprintf(_T("close thread %08X\n"),GetLastError());
WaitForSingleObject(read_Handle[i],INFINITE);
if ( !GetExitCodeThread(read_Handle, &exThread) )
{
_tprintf(_T("GetExitCodeThread %08X\n"),GetLastError());
}
SetLastError(0);
CloseHandle(read_Handle[i]);
_tprintf(_T("GetExitCodeThread %08X\n"),GetLastError());
CloseHandle(check_Thread);
}
DeleteCriticalSection(§ion);
return 1;
}
If you have open file handles to a USB drive when that drive is removed, those file handles will become invalid. Reinserting the USB drive will not reconstitute those handles in such a way that you can continue after resuming a thread.
You will need to:
detect when the device is removed, and close those now-broken handles
when the device is inserted, open the files again and continue whatever you were doing
Your error handlers are returning without calling LeaveCriticalSection, leaving the CS locked and blocking the other threads indefinitely. From the EnterCriticalSection docs:
If a thread terminates while it has ownership of a critical section,
the state of the critical section is undefined.
Those cases also leave the file handles open.