5

Suppose you use a ThreadPool to perform some operations and assume that each operation writes on a file. All threads of ThreadPool are background threads, so they will be terminated when closing the application. What happens if the application is closed while a thread of ThreadPool is writing a file to disk?

VMAtm
  • 27,943
  • 17
  • 79
  • 125
enzom83
  • 8,080
  • 10
  • 68
  • 114
  • It would close the filehandle to the file and stop writing to it, probably ending up in corrupted state of the file. Have you tried doing that? – Yuval Itzchakov Feb 19 '15 at 14:57
  • 2
    I should verify what happens by writing a big file. – enzom83 Feb 19 '15 at 15:05
  • 2
    The result most likely varies with the used FileSystem. FAT will Show other results than NTFS. – TGlatzer Feb 19 '15 at 15:12
  • 2
    In general, if you find yourself needing answers to questions like these (which is useful in and of itself, don't get me wrong) that's probably a sign you should change your design to something that's obviously correct, rather than relying on the good graces of the framework. In other words, if you have to make sure the operations finish, don't use background threads -- or assume your application can be closed at any time and leave its files corrupted, and handle this scenario on startup accordingly. – Jeroen Mostert Feb 19 '15 at 15:14

3 Answers3

7

Operating system will close the file handle as the part of terminating the process.

  • Any pending asynchronous I/O will be canceled
  • Any data in the write buffer which isn't flushed gets lost
Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
4

Read the MSDN article on Foreground and Background threads

ThreadPool threads are background threads. From the article:

When the runtime stops a background thread because the process is shutting down, no exception is thrown in the thread.

The thread simply stops. It executes one instruction, and never executes the next. The FileStream will be closed as part of the CLR clearing up.

canton7
  • 37,633
  • 3
  • 64
  • 77
  • CLR will not close the files. It is the underlying operating system which does that. – Sriram Sakthivel Feb 19 '15 at 15:09
  • If a process gracefully terminates, then finalizers will be called: see http://blog.stephencleary.com/2009/08/finalizers-at-process-exit.html. FileStream's finalizer closes the underlying file handle. – canton7 Feb 19 '15 at 15:11
  • Finalizers will be called as the part of garbage collection only when the instance is unreachable. How come `FileStream` go unreachable when `ThreadPool` threading is writing with it? – Sriram Sakthivel Feb 19 '15 at 15:12
  • 1
    A simple demo app indicates that the FileStream is indeed closed by the CLR before termination. I kick off a new work item on the ThreadPool, which opens a file and waits a second, and has a finalizer which attempts to close the file. The application is terminated within that second. Attempting to close the file in that finalizer causes an ObjectDisposedException, indicating that the CLR's already disposed the FileStream object. Or am I misinterpreting something? – canton7 Feb 19 '15 at 15:19
  • I've just checked too. I tested it with static field. finalizer gets called in Winforms app but when closing the console application using the close button it doesn't gets called. Your answer also seems to be right. +1 – Sriram Sakthivel Feb 19 '15 at 15:23
2

You can easily try this situation by calling Environment.Exit(0) and Environment.Exit(1) method (successfull exit and exit with error). I think that all the handles for the file will be removed, and the only data already written to the disk will remain, without flushing the buffers.

Althrough, the file could became unaccessible with some strange error like The file is being used by another process or something in case of error exiting the process.

VMAtm
  • 27,943
  • 17
  • 79
  • 125
  • 2
    The argument you pass to `.Exit()` doesn't matter; in both cases the application terminates gracefully (meaning `finally`-blocks and finalizers will run). While you're experimenting, try [`Environment.FailFast()`](https://msdn.microsoft.com/library/system.environment.failfast), as that, unlike `Exit()`, is not a graceful termination and will bypass finalizers. Note that flushing buffers is something that *could* be done in a finalizer, but the BCL classes typically don't (which is a shame, since the OS closes handles anyway and that's the only added value the finalizer would have). – Jeroen Mostert Feb 19 '15 at 15:29