Is it possible to access the values from the applicationSettings
section of a loaded app.config file?
I have found an example How do I retrieve appSettings, but I can't find out how to access applicationSettings
this way.
app-configapplication-settingsconfigurationnetvisual studio
Is it possible to access the values from the applicationSettings
section of a loaded app.config file?
I have found an example How do I retrieve appSettings, but I can't find out how to access applicationSettings
this way.
The point of Dispose is to free unmanaged resources. It needs to be done at some point, otherwise they will never be cleaned up. The garbage collector doesn't know how to call DeleteHandle()
on a variable of type IntPtr
, it doesn't know whether or not it needs to call DeleteHandle()
.
Note: What is an unmanaged resource? If you found it in the Microsoft .NET Framework: it's managed. If you went poking around MSDN yourself, it's unmanaged. Anything you've used P/Invoke calls to get outside of the nice comfy world of everything available to you in the .NET Framework is unmanaged – and you're now responsible for cleaning it up.
The object that you've created needs to expose some method, that the outside world can call, in order to clean up unmanaged resources. The method can be named whatever you like:
public void Cleanup()
or
public void Shutdown()
But instead there is a standardized name for this method:
public void Dispose()
There was even an interface created, IDisposable
, that has just that one method:
public interface IDisposable
{
void Dispose()
}
So you make your object expose the IDisposable
interface, and that way you promise that you've written that single method to clean up your unmanaged resources:
public void Dispose()
{
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
}
And you're done. Except you can do better.
What if your object has allocated a 250MB System.Drawing.Bitmap (i.e. the .NET managed Bitmap class) as some sort of frame buffer? Sure, this is a managed .NET object, and the garbage collector will free it. But do you really want to leave 250MB of memory just sitting there – waiting for the garbage collector to eventually come along and free it? What if there's an open database connection? Surely we don't want that connection sitting open, waiting for the GC to finalize the object.
If the user has called Dispose()
(meaning they no longer plan to use the object) why not get rid of those wasteful bitmaps and database connections?
So now we will:
So let's update our Dispose()
method to get rid of those managed objects:
public void Dispose()
{
//Free unmanaged resources
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
//Free managed resources too
if (this.databaseConnection != null)
{
this.databaseConnection.Dispose();
this.databaseConnection = null;
}
if (this.frameBufferImage != null)
{
this.frameBufferImage.Dispose();
this.frameBufferImage = null;
}
}
And all is good, except you can do better!
What if the person forgot to call Dispose()
on your object? Then they would leak some unmanaged resources!
Note: They won't leak managed resources, because eventually the garbage collector is going to run, on a background thread, and free the memory associated with any unused objects. This will include your object, and any managed objects you use (e.g. the
Bitmap
and theDbConnection
).
If the person forgot to call Dispose()
, we can still save their bacon! We still have a way to call it for them: when the garbage collector finally gets around to freeing (i.e. finalizing) our object.
Note: The garbage collector will eventually free all managed objects. When it does, it calls the
Finalize
method on the object. The GC doesn't know, or care, about your Dispose method. That was just a name we chose for a method we call when we want to get rid of unmanaged stuff.
The destruction of our object by the Garbage collector is the perfect time to free those pesky unmanaged resources. We do this by overriding the Finalize()
method.
Note: In C#, you don't explicitly override the
Finalize()
method. You write a method that looks like a C++ destructor, and the compiler takes that to be your implementation of theFinalize()
method:
~MyObject()
{
//we're being finalized (i.e. destroyed), call Dispose in case the user forgot to
Dispose(); //<--Warning: subtle bug! Keep reading!
}
But there's a bug in that code. You see, the garbage collector runs on a background thread; you don't know the order in which two objects are destroyed. It is entirely possible that in your Dispose()
code, the managed object you're trying to get rid of (because you wanted to be helpful) is no longer there:
public void Dispose()
{
//Free unmanaged resources
Win32.DestroyHandle(this.gdiCursorBitmapStreamFileHandle);
//Free managed resources too
if (this.databaseConnection != null)
{
this.databaseConnection.Dispose(); //<-- crash, GC already destroyed it
this.databaseConnection = null;
}
if (this.frameBufferImage != null)
{
this.frameBufferImage.Dispose(); //<-- crash, GC already destroyed it
this.frameBufferImage = null;
}
}
So what you need is a way for Finalize()
to tell Dispose()
that it should not touch any managed resources (because they might not be there anymore), while still freeing unmanaged resources.
The standard pattern to do this is to have Finalize()
and Dispose()
both call a third(!) method; where you pass a Boolean saying if you're calling it from Dispose()
(as opposed to Finalize()
), meaning it's safe to free managed resources.
This internal method could be given some arbitrary name like "CoreDispose", or "MyInternalDispose", but is tradition to call it Dispose(Boolean)
:
protected void Dispose(Boolean disposing)
But a more helpful parameter name might be:
protected void Dispose(Boolean itIsSafeToAlsoFreeManagedObjects)
{
//Free unmanaged resources
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
//Free managed resources too, but only if I'm being called from Dispose
//(If I'm being called from Finalize then the objects might not exist
//anymore
if (itIsSafeToAlsoFreeManagedObjects)
{
if (this.databaseConnection != null)
{
this.databaseConnection.Dispose();
this.databaseConnection = null;
}
if (this.frameBufferImage != null)
{
this.frameBufferImage.Dispose();
this.frameBufferImage = null;
}
}
}
And you change your implementation of the IDisposable.Dispose()
method to:
public void Dispose()
{
Dispose(true); //I am calling you from Dispose, it's safe
}
and your finalizer to:
~MyObject()
{
Dispose(false); //I am *not* calling you from Dispose, it's *not* safe
}
Note: If your object descends from an object that implements
Dispose
, then don't forget to call their base Dispose method when you override Dispose:
public override void Dispose()
{
try
{
Dispose(true); //true: safe to free managed resources
}
finally
{
base.Dispose();
}
}
And all is good, except you can do better!
If the user calls Dispose()
on your object, then everything has been cleaned up. Later on, when the garbage collector comes along and calls Finalize, it will then call Dispose
again.
Not only is this wasteful, but if your object has junk references to objects you already disposed of from the last call to Dispose()
, you'll try to dispose them again!
You'll notice in my code I was careful to remove references to objects that I've disposed, so I don't try to call Dispose
on a junk object reference. But that didn't stop a subtle bug from creeping in.
When the user calls Dispose()
: the handle CursorFileBitmapIconServiceHandle is destroyed. Later when the garbage collector runs, it will try to destroy the same handle again.
protected void Dispose(Boolean iAmBeingCalledFromDisposeAndNotFinalize)
{
//Free unmanaged resources
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle); //<--double destroy
...
}
The way you fix this is tell the garbage collector that it doesn't need to bother finalizing the object – its resources have already been cleaned up, and no more work is needed. You do this by calling GC.SuppressFinalize()
in the Dispose()
method:
public void Dispose()
{
Dispose(true); //I am calling you from Dispose, it's safe
GC.SuppressFinalize(this); //Hey, GC: don't bother calling finalize later
}
Now that the user has called Dispose()
, we have:
There's no point in the GC running the finalizer – everything's taken care of.
The documentation for Object.Finalize
says:
The Finalize method is used to perform cleanup operations on unmanaged resources held by the current object before the object is destroyed.
But the MSDN documentation also says, for IDisposable.Dispose
:
Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
So which is it? Which one is the place for me to cleanup unmanaged resources? The answer is:
It's your choice! But choose
Dispose
.
You certainly could place your unmanaged cleanup in the finalizer:
~MyObject()
{
//Free unmanaged resources
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
//A C# destructor automatically calls the destructor of its base class.
}
The problem with that is you have no idea when the garbage collector will get around to finalizing your object. Your un-managed, un-needed, un-used native resources will stick around until the garbage collector eventually runs. Then it will call your finalizer method; cleaning up unmanaged resources. The documentation of Object.Finalize points this out:
The exact time when the finalizer executes is undefined. To ensure deterministic release of resources for instances of your class, implement a Close method or provide a
IDisposable.Dispose
implementation.
This is the virtue of using Dispose
to cleanup unmanaged resources; you get to know, and control, when unmanaged resource are cleaned up. Their destruction is "deterministic".
To answer your original question: Why not release memory now, rather than for when the GC decides to do it? I have a facial recognition software that needs to get rid of 530 MB of internal images now, since they're no longer needed. When we don't: the machine grinds to a swapping halt.
For anyone who likes the style of this answer (explaining the why, so the how becomes obvious), I suggest you read Chapter One of Don Box's Essential COM:
In 35 pages he explains the problems of using binary objects, and invents COM before your eyes. Once you realize the why of COM, the remaining 300 pages are obvious, and just detail Microsoft's implementation.
I think every programmer who has ever dealt with objects or COM should, at the very least, read the first chapter. It is the best explanation of anything ever.
When everything you know is wrong archiveby Eric Lippert
It is therefore very difficult indeed to write a correct finalizer, and the best advice I can give you is to not try.
Updated NOTE on this solution: Checking with FileAccess.ReadWrite
will fail for Read-Only files so the solution has been modified to check with FileAccess.Read
.
ORIGINAL: I've used this code for the past several years, and I haven't had any issues with it.
Understand your hesitation about using exceptions, but you can't avoid them all of the time:
protected virtual bool IsFileLocked(FileInfo file)
{
try
{
using(FileStream stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None))
{
stream.Close();
}
}
catch (IOException)
{
//the file is unavailable because it is:
//still being written to
//or being processed by another thread
//or does not exist (has already been processed)
return true;
}
//file is not locked
return false;
}
Best Answer
The applicationSettings are readonly during runtime. You can set/modify them either via a text editor in the app.config file directly, but it is recommended to open the project properties in Visual Studio and select the "Settings" tab. It is important to set the right scope:
For example, if you create myOwnSetting in your project WindowsFormsTestApplication1 as follows (change the scope to "Application"):
it will add the following to the application's app.config file:
Visual Studio creates C# code to access this setting automatically (this is why you should do it in the project properties and not via text editor) - after you have saved the changes, from within the same namespace you can read its value in the application easily via the following code:
Given the
applicationSettings
in the listing above, this would retrieve the string "Hi there!" for the variablecurrentValue
.Note that if you have created myOwnSetting for the "User" scope, then it is stored in a section named
<userSettings>
instead of<applicationSettings>
, but you still can access it with the code line above.Another difference of scope "User" settings is that you have read-write access, i.e. it is allowed to do the following:
If you try the same with the "Application" scope setting myOwnSetting, it would result in a compile-time error telling you that it is read-only.
If you re-start the application, you will notice that myUserSetting has changed to the value "Something else" - but the old value is still in the app.config. Why is this so? The reason is that it is regarded as a default value - and as I said earlier, the "User" scope is bound to the user profile. As a consequence, the value "Something else" is stored in
in a file named
User.config
, which looks as follows:You can't exactly tell the path as it is created automatically by the .NET Framework, and it will look different on your PC. But you can see that USERID is the Windows user ID of your current user, FIRMNAME is part of the assembly information you have specified, and the assembly name and version is also used in the path.
Note:
The
<sectionGroup>
with<section>
declaration is mandatory and its name attribute needs to match with the namespace. The namespace must appear exactly once in the configuration, and there is only oneapplicationSettings
section allowed.As you could see in the config file, the namespace is mentioned explicitly there (
WindowsFormsTestApplication1.Properties.Settings
). As a consequence, if you want to access the settings from code not being in the same namespace you might need to use a fully qualified reference. Having said that, be careful if you copy the entire<applicationSettings>...</applicationSettings>
section from one application's config to another - you might need to change the namespace in the target config afterwards.If you're using the Settings Designer (Settings tab in your project), it will create a file named
Settings.Settings
(along withSettings.Designer.cs
to access the sessings via C# code) in the Properties section of your project. This is a copy of the settings as it will be stored in yourWeb.config
orApp.config
file as well (depending on your project type, only for application scope settings - user scope settings are stored based on the user profile). You can create additional*.settings
files and use them (as it is described here).If you're not using the settings designer, or if you're using a tool like LinqPad, you might need to use a different approach. Consider this:
You can read string type
applicationSettings
by treating the configuration as anXDocument
. The example given is limited to the string type and you can retrieve the setting from the app.config example above as follows:var value=GetApplicationSetting("myOwnSetting", "WindowsFormsTestApplication1.Properties.Settings");
Likewise, you can create a similar function GetUserSetting for the default
<userSettings>
section: Just copy the code above, rename the function name and replaceapplicationSettings
in thexPathStr
byuserSettings
.There is an upgrade method available for user settings, which is described here. More details about the location where user settings are stored can be found there.
The
<appSettings>
section in the configuration works differently, since it does not distinguish "User" and "Application" scope and it does not support different datatypes, just strings. However, it is possible to easily read and write the configuration keys/values. If you're interested in the code, you can find it here (on stackoverflow):how to read/write config settings of appSettings
If you are uncertain whether you should use
AppSettings
orapplicationSettings
, then read this before you decide it.