I am using the fileSystemWatcher and the _Changed event to indicate what file that was LastWritten to in a folder and then I want to read this file.
It seems that the code that I have below is executing twice and the second time the code runs I get this error message.
I have tried other type of code that also indicates that the code executes twice. ?

Why does the code execute twice though I want to just execute one time.
Second is even if the code is executing twice the file shouldn´t be used as I am closing it ? and there is no other process that use the file.

"The process cannot access the file 'C:\\F1\\t1.txt' because it is being used by another process"

private: System::Void fileSystemWatcher1_Changed(System::Object^  sender, System::IO::FileSystemEventArgs^  e) 
{
			
String^ RLine;
StreamReader^ ar;
ar = gcnew StreamReader(e->FullPath->ToString());

	while( ar->Peek() >= 0 ) 
	{
		RLine = ar->ReadLine();
	}
	 ar->Close();

}

Recommended Answers

All 7 Replies

If the FileSystemWatcher is running in asynchronous mode, events will fire when they happen, and if the handler relies on having an exclusive lock, you'll get an error. Here's the kicker though: when the changed event is fired and you open the file, the access time will change and fire the event again.

Your best bet in this case would be to treat the FileSystemWatcher like a timer. When it ticks, stop it long enough to do what you want to do, then start it again.

Thanx Narue, I have to check for some things here.

>> if the handler relies on having an exclusive lock, you'll get an error

What meens by this. What is an exclusive lock ?

>> treat the FileSystemWatcher like a timer. When it ticks, stop it long enough to do what you want to do, then start it again.

I wonder how these events is executing 2 times. I have tried to put a flag(rem) to not execute the event 2 times. I did this only to test how this works but I get the same error here that the file is in use by another process.

The question here though is that I wonder how the timer will work.
What is it that ticks ? Because I dont want to predefine a time where the event is 'dead' for taking in a LastWritten file event. This is what I wonder by "stop it long enough"
In somehow I want to use realtime flags that can block.

NotifyFilter is "LastWrite"

if( e->FullPath->ToString() != rem )
{
    //Read a file
}			 
rem = e->FullPath->ToString();

>What meens by this. What is an exclusive lock ?
It means the file can only be opened by one thread at a time. Exclusive access is the default open mode, but you can change that to shared if you need to. However, having one thread read from the file and another write to the file simultaneously is rather difficult to get right.

>I did this only to test how this works but I get the
>same error here that the file is in use by another process.
I'd guess that whoever is writing the file isn't done yet. Try waiting for 30 seconds or so and then read the file. If it works that's probably the problem.

>NotifyFilter is "LastWrite"
Nevermind then. Your event handler shouldn't cause the changed event to fire unless you also poll for the last access.

okay, I have tried out this way to put it to sleep for 1 millisecond and this works. I get no errors that the file is in use the second time the event is shoot.
My settings are:

GenerateMember True
Modifiers Private
EnableRaisingEvents True
Filter *.txt
IncludeSubdirectories False
NotifyFilter LastWrite
Path C:\TEST

private: System::Void fileSystemWatcher1_Changed(System::Object^  sender, System::IO::FileSystemEventArgs^  e) 
{
			 
Thread::Sleep(1); //1 millisec
	
String^ RLine;
ar = gcnew StreamReader(e->FullPath->ToString());

	while( ar->Peek() >= 0 ) 
	{
		RLine = ar->ReadLine();
	}
	 ar->Close();
}

What I do is that I open one file manually by clicking on it in the path "TEST".
Then I add some text, close the file manually and press Yes on saving the changes.
When I click Yes, this event is shooting and then put to sleep for 1 millisecond and then shooting again ?

As I have put the filter to "LastWrite" why does the event shoot 2 times because I limit it to just LastWrite and are not using the "LastAccess" also.
I have googled around about this and it seems to be a problem but cant find any solution or good explanation what really happens in this case.
How could the second shoot be prevented.

>How could the second shoot be prevented.
You need to figure out where it's coming from, then if you have control over that part, change it so that the second event isn't fired. Otherwise, write your event handler so that it doesn't choke on events in quick succession.

As I have put the filter to "LastWrite" why does the event shoot 2 times because I limit it to just LastWrite and are not using the "LastAccess" also.

I guess that your editor makes calls to Windows API functions that cause the event to occur twice. You might write a simple test program which does a fopen()/fwrite()/fclose() sequence, the event probably fires only once in that case.

I have googled around about this and it seems to be a problem but cant find any solution or good explanation what really happens in this case.

If you want to know what actually takes place when you modify the file, then you might find
Process Monitor from SysInternals quite useful. You'll be able to easily capture all related filesystem events.

Thanx for this tips! I have worked out this test also using the ProcessMonitor.
Using this code it still executes twice.
I try to understand from the ProcessMonitorlog that I attached wich of the happenings that can occur the watcherevent to execute twice for "LastWrite" or/and what could be attached to this code to prevent perheps.

open(), write(), close()

ofstream o1;
o1.open("C:\\test\\trew.txt");

o1<< "hello";
o1.close();

LastWrite NotifyFilter for Path "C:\\test"
Below code executes 2 times. Should be executed 1 time only.

private: System::Void fileSystemWatcher1_Changed(System::Object^  sender, System::IO::FileSystemEventArgs^  e) 
{			 

ar = gcnew StreamReader("C:\\H.txt");			 
		 
String^ RLine;
			 
	while( ar->Peek() >= 0 ) 
	{
		RLine = ar->ReadLine();
	}
	 ar->Close();

}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.