PC Review


Reply
Thread Tools Rate Thread

determine if file is being used by another process

 
 
Gabe Moothart
Guest
Posts: n/a
 
      15th Feb 2005
Hi,
I'm writing a windows service which interacts with a separate process.
Basically, it calls a process which creates a file, and then my service
reads that file. The problem is, the external process can take a second
or two to finish writing the file. If I try to read the file to soon, I
get an exception that "The process cannot access the file because it is
being used by another process".

I could just set a timer, but the time it takes the external process to
create the file is highly variable, and I'd rather not wait longer than
I have to. What I'd like to do is run a loop that constantly checks the
status of that file (basically a "busy waiting" loop) and only allows
the File.OpenRead() when it can succeed. Right now I'm using this
monstrosity:

-------------------------------8<-------------------------
FileStream fs;
ReadFile:
try
{
fs = File.OpenRead("TestFile.txt");
}
catch(IOException)
{
goto ReadFile;
}
-------------------------------8<-------------------------

But there has to be a better way. Any suggestions?

thanks,
Gabe
 
Reply With Quote
 
 
 
 
Nicholas Paldino [.NET/C# MVP]
Guest
Posts: n/a
 
      15th Feb 2005
Gabe,

Instead of doing that, I would recommend declaring the CreateFile API
function so that you can call it through the P/Invoke layer. The CreateFile
function will return an error code if you can not access the file, which is
much cleaner than handling the exception.

Once you have that, if you are able to open the file with the CreateFile
API, then you can pass the handle to the FileStream constructor, which takes
a file handle.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (E-Mail Removed)

"Gabe Moothart" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Hi,
> I'm writing a windows service which interacts with a separate process.
> Basically, it calls a process which creates a file, and then my service
> reads that file. The problem is, the external process can take a second or
> two to finish writing the file. If I try to read the file to soon, I get
> an exception that "The process cannot access the file because it is being
> used by another process".
>
> I could just set a timer, but the time it takes the external process to
> create the file is highly variable, and I'd rather not wait longer than I
> have to. What I'd like to do is run a loop that constantly checks the
> status of that file (basically a "busy waiting" loop) and only allows the
> File.OpenRead() when it can succeed. Right now I'm using this monstrosity:
>
> -------------------------------8<-------------------------
> FileStream fs;
> ReadFile:
> try
> {
> fs = File.OpenRead("TestFile.txt");
> }
> catch(IOException)
> {
> goto ReadFile;
> }
> -------------------------------8<-------------------------
>
> But there has to be a better way. Any suggestions?
>
> thanks,
> Gabe



 
Reply With Quote
 
Gabe Moothart
Guest
Posts: n/a
 
      15th Feb 2005
Nicholas,
Thanks, that's just what I needed.

Gabe

> Gabe,
>
> Instead of doing that, I would recommend declaring the CreateFile API
> function so that you can call it through the P/Invoke layer. The CreateFile
> function will return an error code if you can not access the file, which is
> much cleaner than handling the exception.
>
> Once you have that, if you are able to open the file with the CreateFile
> API, then you can pass the handle to the FileStream constructor, which takes
> a file handle.
>
> Hope this helps.
>
>

 
Reply With Quote
 
Willy Denoyette [MVP]
Guest
Posts: n/a
 
      15th Feb 2005

"Nicholas Paldino [.NET/C# MVP]" <(E-Mail Removed)> wrote in
message news:(E-Mail Removed)...
> Gabe,
>
> Instead of doing that, I would recommend declaring the CreateFile API
> function so that you can call it through the P/Invoke layer. The
> CreateFile function will return an error code if you can not access the
> file, which is much cleaner than handling the exception.
>
> Once you have that, if you are able to open the file with the
> CreateFile API, then you can pass the handle to the FileStream
> constructor, which takes a file handle.
>
> Hope this helps.
>


Sorry to ask, but why do you thing it's much cleaner to PInvoke instead of
handling the exception?
You have to test the return value of CreateFile, and only retry the call if
the file is in use, but you have to test for other error conditions too and
take appropriate actions (throw or ..). IMO when all is done (correctly )you
will have coded a great deal of what's been done in File.OpenRead.

Note also that v2's FileStream constructors that accept an IntPtr as handle
are deprecated, so you will have to encapsulate the handle returned in a
SafeHandle before passing to the FileStream ctor.


Willy.



 
Reply With Quote
 
Nicholas Paldino [.NET/C# MVP]
Guest
Posts: n/a
 
      15th Feb 2005
Willy,

The OP is trying to handle business logic depending on whether or not
the file is in use. When coding business logic, flow control, IMO, should
never be predicated on exception handling, especially when there is a way to
check the status.

Of course, this is a matter of preference. If other people want to base
their logic on exception handling, they are free to do so, but I think there
is a strong camp that disagrees with this approach.

Also, the OP specifically asked for a solution that did not involve
using exceptions to determine if the file was in use.

From a performance standpoint, I think that the seven or so extra
instructions to call API through the P/Invoke layer (which are going to be
called anyways by the constructor if you didn't pass in a file handle) are a
small price to pay as opposed to throwing an exception.

You are right about the constructor being marked as obsolete and passing
a SafeHandle. I didn't mention it because I assume that most people are not
using the beta, but the OP should know that as well.


--
- Nicholas Paldino [.NET/C# MVP]
- (E-Mail Removed)

"Willy Denoyette [MVP]" <(E-Mail Removed)> wrote in message
news:%(E-Mail Removed)...
>
> "Nicholas Paldino [.NET/C# MVP]" <(E-Mail Removed)> wrote
> in message news:(E-Mail Removed)...
>> Gabe,
>>
>> Instead of doing that, I would recommend declaring the CreateFile API
>> function so that you can call it through the P/Invoke layer. The
>> CreateFile function will return an error code if you can not access the
>> file, which is much cleaner than handling the exception.
>>
>> Once you have that, if you are able to open the file with the
>> CreateFile API, then you can pass the handle to the FileStream
>> constructor, which takes a file handle.
>>
>> Hope this helps.
>>

>
> Sorry to ask, but why do you thing it's much cleaner to PInvoke instead of
> handling the exception?
> You have to test the return value of CreateFile, and only retry the call
> if the file is in use, but you have to test for other error conditions too
> and take appropriate actions (throw or ..). IMO when all is done
> (correctly )you will have coded a great deal of what's been done in
> File.OpenRead.
>
> Note also that v2's FileStream constructors that accept an IntPtr as
> handle are deprecated, so you will have to encapsulate the handle returned
> in a SafeHandle before passing to the FileStream ctor.
>
>
> Willy.
>
>
>



 
Reply With Quote
 
Willy Denoyette [MVP]
Guest
Posts: n/a
 
      15th Feb 2005

"Nicholas Paldino [.NET/C# MVP]" <(E-Mail Removed)> wrote in
message news:(E-Mail Removed)...
> Willy,
>
> The OP is trying to handle business logic depending on whether or not
> the file is in use. When coding business logic, flow control, IMO, should
> never be predicated on exception handling, especially when there is a way
> to check the status.
>
> Of course, this is a matter of preference. If other people want to
> base their logic on exception handling, they are free to do so, but I
> think there is a strong camp that disagrees with this approach.
>
> Also, the OP specifically asked for a solution that did not involve
> using exceptions to determine if the file was in use.
>
> From a performance standpoint, I think that the seven or so extra
> instructions to call API through the P/Invoke layer (which are going to be
> called anyways by the constructor if you didn't pass in a file handle) are
> a small price to pay as opposed to throwing an exception.
>
> You are right about the constructor being marked as obsolete and
> passing a SafeHandle. I didn't mention it because I assume that most
> people are not using the beta, but the OP should know that as well.
>
>


Nicholas,

I'm not talking about the performance differences between both, I'm talking
about the extra lines of code that are needed to make it more robust,
especially in the case of a windows service.
And IMO it's pretty wrong to loop on CreateFile calls [without any sleep in
between (pun intended) - see later] and only terminate the loop when the
status is OK. What if the status is something like "access denied or file
does not exist or wrong open mode" you will have to exit the loop and take
an action don't you think so?
Now whiter you handle exceptions or error codes, you should never call an
API like CreateFile is a closed loop without some sleep in between the
calls.
If you average file creation time is something like 1 sec., put a sleep of
0.5 - 1 sec. in between the calls, handle the exception or the error return
and retry when still busy. That way you will only throw a very few times per
file you process. However, if you keep your closed loop your thread will
consume most if not all CPU resources and disturb the external process in
such a way that it can dramatically increase the file creation time when run
on a single CPU box.

Willy.



 
Reply With Quote
 
Nicholas Paldino [.NET/C# MVP]
Guest
Posts: n/a
 
      15th Feb 2005
Willy,

The problem you describe will exist in both cases, and the solution
would be the same in both cases. Basically, the thread should be put to
sleep in between checks. Whether or not the OP uses exceptions to determine
the cause of the error, or the result from CreateFile, the need to put the
thread to sleep in that loop is still needed.


--
- Nicholas Paldino [.NET/C# MVP]
- (E-Mail Removed)

"Willy Denoyette [MVP]" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
>
> "Nicholas Paldino [.NET/C# MVP]" <(E-Mail Removed)> wrote
> in message news:(E-Mail Removed)...
>> Willy,
>>
>> The OP is trying to handle business logic depending on whether or not
>> the file is in use. When coding business logic, flow control, IMO,
>> should never be predicated on exception handling, especially when there
>> is a way to check the status.
>>
>> Of course, this is a matter of preference. If other people want to
>> base their logic on exception handling, they are free to do so, but I
>> think there is a strong camp that disagrees with this approach.
>>
>> Also, the OP specifically asked for a solution that did not involve
>> using exceptions to determine if the file was in use.
>>
>> From a performance standpoint, I think that the seven or so extra
>> instructions to call API through the P/Invoke layer (which are going to
>> be called anyways by the constructor if you didn't pass in a file handle)
>> are a small price to pay as opposed to throwing an exception.
>>
>> You are right about the constructor being marked as obsolete and
>> passing a SafeHandle. I didn't mention it because I assume that most
>> people are not using the beta, but the OP should know that as well.
>>
>>

>
> Nicholas,
>
> I'm not talking about the performance differences between both, I'm
> talking about the extra lines of code that are needed to make it more
> robust, especially in the case of a windows service.
> And IMO it's pretty wrong to loop on CreateFile calls [without any sleep
> in between (pun intended) - see later] and only terminate the loop when
> the status is OK. What if the status is something like "access denied or
> file does not exist or wrong open mode" you will have to exit the loop and
> take an action don't you think so?
> Now whiter you handle exceptions or error codes, you should never call an
> API like CreateFile is a closed loop without some sleep in between the
> calls.
> If you average file creation time is something like 1 sec., put a sleep of
> 0.5 - 1 sec. in between the calls, handle the exception or the error
> return and retry when still busy. That way you will only throw a very few
> times per file you process. However, if you keep your closed loop your
> thread will consume most if not all CPU resources and disturb the external
> process in such a way that it can dramatically increase the file creation
> time when run on a single CPU box.
>
> Willy.
>
>
>



 
Reply With Quote
 
Willy Denoyette [MVP]
Guest
Posts: n/a
 
      15th Feb 2005


"Nicholas Paldino [.NET/C# MVP]" <(E-Mail Removed)> wrote in
message news:(E-Mail Removed)...
> Willy,
>
> The problem you describe will exist in both cases, and the solution
> would be the same in both cases. Basically, the thread should be put to
> sleep in between checks. Whether or not the OP uses exceptions to
> determine the cause of the error, or the result from CreateFile, the need
> to put the thread to sleep in that loop is still needed.
>
>
> --


Nicholas,

Agreed, and that's exactly why I prefer to use the FCL and handle the
exceptions, I don't need to declare the PInvoke (maintenance issue!!) stuff
and other extra code, it's already there in the framework, the exception
overhead is IMO a non issue.

Willy.


 
Reply With Quote
 
tkondal@gmail.com
Guest
Posts: n/a
 
      16th Feb 2005
I agree with Willy. There is just too much overhead for nothing in
using the CreateFile API call. I, personally, think that exception
handling is a better way of doing it.

 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to determine which process is using a file. =?Utf-8?B?SlA=?= Windows XP General 1 14th Apr 2006 02:59 PM
How to determine if a File is opened by another process? =?Utf-8?B?Ui4gTmFjaHRzdHVybQ==?= Microsoft Dot NET Framework 2 12th Dec 2005 04:14 PM
How do you determine the owner of a process Ken Soenen Microsoft VB .NET 4 9th Aug 2005 11:12 PM
Determine service from process TieTo Microsoft VB .NET 0 19th Apr 2005 09:40 PM
determine name of process handling a file Dariusz Tomoń Windows XP General 1 4th Mar 2004 08:47 AM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 07:50 PM.