Is it safe to use static methods on File class in C#?

Sunil

I have following code in code-behind of an ASP.Net app, where a file is being read followed by writing to the file.

Code

var state= File.ReadAllText(Server.MapPath(string.Format("~/state/{0}", fileName)));
if(state.indexOf("1") == 0) 
{
  File.WriteAllText(Server.MapPath(string.Format("~/state/{0}", fileName)), newState);
}

Sometimes, but not always, I get the following exception.

Exception

The process cannot access the file 'C:\inetpub\wwwroot\mywebsite1\state\20150905005929435_edf9267e-fad1-45a7-bfe2-0e6e643798b5' because it is being used by another process.

I am guessing that the file read operation sometimes is not closing the file before the write operation happens, Or may be the file write operation is not closing the file before the next request from web application comes. But, I cannot find what exactly is the reason.

Question: How can I avoid this error from happening? Is it not safe to use the File class and instead use the traditional approach of FileStream object where I would always dispose the FileStream object explicitly?

UPDATE 1

I tried a retry loop approach, but even that didn't seem to solve the problem , since I was able to reproduce the same error if the ASP.Net page was submitted very quickly multiple times one after another. So I am back to finding a fool-proof solution in my case.

  string state = null;
  int i = 0;
  while (i < 20) {
    try {

        state = File.ReadAllText(Server.MapPath(string.Format("~/state/{0}", fileName)));

    } catch (Exception ex2) {
        //log exception
        Elmah.ErrorSignal.FromCurrentContext().Raise(ex2);
        //if even retry doesn't work then throw an exception
        if (i == 19) {
            throw;
        }
        //sleep for a few milliseconds
        System.Threading.Thread.Sleep(10);
    }
    i++;
  }

  i = 0;
  while (i < 20) {
    try {


        File.WriteAllText(Server.MapPath(string.Format("~/state/{0}", fileName)), newState);

    } catch (Exception ex2) {
        //log exception
        Elmah.ErrorSignal.FromCurrentContext().Raise(ex2);
        //if even retry doesn't work then throw an exception
        if (i == 19) {
            throw;
        }
        //sleep for a few milliseconds
        System.Threading.Thread.Sleep(10);
    }
    i++;
  }

UPDATE 2

The only fool proof solution that seemed to work is by using a File Sequencing approach, as suggested by usr. This involves writing to a different file and not to the same file that was just read. The name of file being written to is the name of file that was just read appended by a sequence number.

  string fileName = hiddenField1.Value;
  string state = null;
  int i = 0;
  while (i < 20) {
    try {

        state = File.ReadAllText(Server.MapPath(string.Format("~/state/{0}", fileName)));

    } catch (Exception ex2) {
        //log exception
        Elmah.ErrorSignal.FromCurrentContext().Raise(ex2);
        //if even retry doesn't work then throw an exception
        if (i == 19) {
            throw;
        }
        //sleep for a few milliseconds
        System.Threading.Thread.Sleep(10);
    }
    i++;
  }

  i = 0;
  while (i < 20) {
    try {
        //***************FILE SEQUENCING**************************
        //Change the file to which state is written, so no concurrency errors happen 
        //between reading from and writing to same file. This is a fool-proof solution.
        //Since max value of integer is more than 2 billion i.e. 2,147,483,647
        //so we can be sure that our sequence will never run out of limits because an ASP.Net page
        //is not going to postback 2 billion times
        if (fileName.LastIndexOf("-seq_") >= 0) {
            fileName = fileName.Substring(0, fileName.LastIndexOf("-seq_") + 4 + 1) + (int.Parse(fileName.Substring(fileName.LastIndexOf("-seq_") + 4 + 1)) + 1);
        } else {
            fileName = fileName + "-seq_1";
        }
        //change the file name so in next read operation the new file is read
        hiddenField1.Value = fileName;
        File.WriteAllText(Server.MapPath(string.Format("~/state/{0}", fileName)), newState);

    } catch (Exception ex2) {
        //log exception
        Elmah.ErrorSignal.FromCurrentContext().Raise(ex2);
        //if even retry doesn't work then throw an exception
        if (i == 19) {
            throw;
        }
        //sleep for a few milliseconds
        System.Threading.Thread.Sleep(10);
    }
    i++;
  }

The only downside to above approach is that many files would get created as end users post back to the same ASP.Net page. So, it would be good to have a background job that deleted stale files so number of files would be minimized.

File Names with sequencing

File Sequencing Naming

UPDATE 3

Another fool proof solution is to alternate between read and write file names. This way we do not end up creating many files and only use 2 files as the end user posts back to the same page many times. The code is same as in code under UPDATE 2 except the code after FILE SEQUENCING comment should be replaced by code below.

if (fileName.LastIndexOf("-seq_1") >= 0) {
            fileName = fileName.Substring(0, fileName.LastIndexOf("-seq_1"));
        } else {
            fileName = fileName + "-seq_1";
        }

File Names with Alternating approach File Alternating Approach

usr

I am guessing that the file read operation sometimes is not closing the file before the write operation happens, Or may be the file write operation is not closing the file before the next request from web application comes.

Correct. File systems do not support atomic updates well. (Especially not on Windows; many quirks.)

Using FileStream does not help. You would just rewrite the same code that the File class has. File has no magic inside. It just uses FileStream wrapped for your convenience.

Try keeping files immutable. When you want to write a new contents write a new file. Append a sequence number to the file name (e.g. ToString("D9")). When reading pick the file with the highest sequence number.

Or, just add a retry loop with a small delay.

Or, use a better data store such as a database. File systems are really nasty. This is an easy problem to solve with SQL Server for example.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

When to use static and class methods

From Dev

Is it safe to use static methods in J2EE WebFilter filters?

From Dev

Is there a workaround to use static methods by a generic class?

From Dev

Instantiate a class to call a method or use static methods?

From Dev

Is there a workaround to use static methods by a generic class?

From Dev

Python: separate utilities file or use static methods?

From Dev

where static / class methods are stored in objective c

From Dev

Cython C++ static methods in a template class

From Dev

use Guava CharMatcher as a static fields in a class . Is CharMatcher thread safe?

From Dev

is it safe to use .net static Path class when using TPL?

From Dev

Java: Use Static methods of Parent Class in Child Class

From Dev

Java: Use Static methods of Parent Class in Child Class

From Dev

C++ static variables in static class methods defined in headers

From Dev

Get the static methods of a class

From Dev

Implementing Static Methods In A Class

From Dev

What is the reason you can't use static methods/variables in a class

From Dev

Use of a friend class to hide private static callback methods

From Dev

Why PowerShell use double colon( :: ) to call static methods of a .NET class?

From Dev

Is it OK to use the static utility methods found in the Whitebox class?

From Dev

Java - Only one instance of class: use static methods instead?

From Dev

I have a aspx file calling a static class with a static function. Is this thread safe

From Dev

Use Mockito to mock java.nio.file.Files static methods

From Dev

Use Mockito to mock java.nio.file.Files static methods

From Java

Is reference to this safe to use in a class?

From Dev

How to call static methods of parent class in Objective - C.

From Dev

C++ abstract class static methods showing in derived classes

From Dev

When extending class with static methods that I don't actually use, will those methods be compiled?

From Dev

Is static function thread safe in C?

From Dev

How to decorate class or static methods

Related Related

  1. 1

    When to use static and class methods

  2. 2

    Is it safe to use static methods in J2EE WebFilter filters?

  3. 3

    Is there a workaround to use static methods by a generic class?

  4. 4

    Instantiate a class to call a method or use static methods?

  5. 5

    Is there a workaround to use static methods by a generic class?

  6. 6

    Python: separate utilities file or use static methods?

  7. 7

    where static / class methods are stored in objective c

  8. 8

    Cython C++ static methods in a template class

  9. 9

    use Guava CharMatcher as a static fields in a class . Is CharMatcher thread safe?

  10. 10

    is it safe to use .net static Path class when using TPL?

  11. 11

    Java: Use Static methods of Parent Class in Child Class

  12. 12

    Java: Use Static methods of Parent Class in Child Class

  13. 13

    C++ static variables in static class methods defined in headers

  14. 14

    Get the static methods of a class

  15. 15

    Implementing Static Methods In A Class

  16. 16

    What is the reason you can't use static methods/variables in a class

  17. 17

    Use of a friend class to hide private static callback methods

  18. 18

    Why PowerShell use double colon( :: ) to call static methods of a .NET class?

  19. 19

    Is it OK to use the static utility methods found in the Whitebox class?

  20. 20

    Java - Only one instance of class: use static methods instead?

  21. 21

    I have a aspx file calling a static class with a static function. Is this thread safe

  22. 22

    Use Mockito to mock java.nio.file.Files static methods

  23. 23

    Use Mockito to mock java.nio.file.Files static methods

  24. 24

    Is reference to this safe to use in a class?

  25. 25

    How to call static methods of parent class in Objective - C.

  26. 26

    C++ abstract class static methods showing in derived classes

  27. 27

    When extending class with static methods that I don't actually use, will those methods be compiled?

  28. 28

    Is static function thread safe in C?

  29. 29

    How to decorate class or static methods

HotTag

Archive