• 0

[C#] Releasing resources - images


Question

I am having a bit of trouble at the moment releasing resources located on my machine.

This sample program I built demonstrates the problem im having.

I created a WPF form with an image control and two buttons.

		private void addButton_Click(object sender, RoutedEventArgs e)
		{
			image1.Source = new BitmapImage(new Uri(@"C:\Users\Username\Pictures\Snow Day\100_0918.jpg", UriKind.RelativeOrAbsolute));
		}

		private void removeButton_Click(object sender, RoutedEventArgs e)
		{
			image1.Source = null;
			image1 = null;
		}

I want to be able to delete this image after i have stopped using the image without having to close the program.

post-16640-1247671880.png

BTW... I know that I could convert the image into a Byte array and display it without holding the resource.

This is only a sample program posted above. The real problem is too complicated to describe.

Thanks

Edited by Guest
Link to comment
Share on other sites

22 answers to this question

Recommended Posts

  • 0

As a general rule anything to do with Graphics and IO, make sure you dispose of the objects. The GC doesn't clean up straight away. Calling Dispose ensures that those system resources are released. File locks are such resources.

Link to comment
Share on other sites

  • 0

			Image image1 = new Image();
			BitmapImage bitImage = new BitmapImage(new Uri(@"C:\Users\Enda Quigley\Pictures\Snow Day\100_0918.jpg", UriKind.RelativeOrAbsolute));
			image1.Source = bitImage;

Sorry... image1 is of type Image.

I was looking for the dispose method but neither Image or BitmapImage has the dispose method.

:s

Link to comment
Share on other sites

  • 0

Also you might want to call the garbage collector at the end of this, to insure that it's released asap

GC.Collect

Hope that helps.

Link to comment
Share on other sites

  • 0

Having a scan through the MSDN, there doesn't seem to be a dispose method around the System.Windows.Controls.Image object at all, which is odd. Your best bet is to try what James said, and to put GC.Collect(); after you have nullified the image and the source.

Link to comment
Share on other sites

  • 0

Hm, looked through the interface of BitmapImage and Image and I can't see any method for releasing resources. GC.Collect() is bad practice, it's expensive and it doesn't guarantee any particular resource will actually be freed.

What you could do is cache your images. Have your program create its own "temp" folder and instead of opening images directly, copy them in the temp folder and open the copies instead. The next time the application starts, clear the temp folder.

It's ugly but that's the best I could come up with, since I've never used WPF.

Link to comment
Share on other sites

  • 0
GC.Collect() is bad practice, it's expensive and it doesn't guarantee any particular resource will actually be freed.

I know this will sound like bait, please take it as a real question. Why is calling GC.Collect bad practice?

Thanks,

James

Link to comment
Share on other sites

  • 0

BitmapImage.StreamSource.Dispose()

for more info check this link

According to this setting CacheOption property to BitmapCacheOption.OnLoad is enough ...

Edit:

GC.Collect is bad practice because in most cases (yes there are exceptions) the .NET Framework knows best when to trigger garbage collection (several heuristics are involved so that the optimal time for collection is chosen, or when resources allocation is at its limits).

Edited by georgevella
Link to comment
Share on other sites

  • 0
I know this will sound like bait, please take it as a real question. Why is calling GC.Collect bad practice?

Thanks,

James

- A garbage collection is an expensive operation. It forces interrupting all threads, walking the heap, compacting memory, reassigning references...

- The CLR knows best when to run a garbage collection.

- Calling GC.Collect() as a method of deterministic finalization is advantageously replaced by implementing IDisposable, since finalizers delay garbage collection, slowing down the application even more.

Bad practice doesn't mean it should never be used, but that in most cases there's a better way of achieving the same effect. GC.Collect() fits the definition nicely.

Link to comment
Share on other sites

  • 0
BitmapImage.StreamSource.Dispose()

for more info check this link

According to this setting CacheOption property to BitmapCacheOption.OnLoad is enough ...

Edit:

GC.Collect is bad practice because in most cases (yes there are exceptions) the .NET Framework knows best when to trigger garbage collection (several heuristics are involved so that the optimal time for collection is chosen, or when resources allocation is at its limits).

Thats it... thanks a million.

I love working with WPF but its little things like this that annoy me.

Link to comment
Share on other sites

  • 0

Informative thread :)

Strange about the lack of Dispose() methods in the control though, I consider it good practice that if a class uses an IDisposable objects, it should itself implement IDisposable. (dis)agree?

Link to comment
Share on other sites

  • 0

No point making a new topic as this problem has the same symptoms.

I just found out yesterday that assemblies could not be unloaded from the program unless they are loaded into a separate AppDomain.

Once you are finish with the .dll file, you should be able to unload the AppDomain itself.

			AppDomain myDomain = AppDomain.CreateDomain("Quigley");
			Assembly myAssembly = myDomain.Load("Toolkit_API");

			// do stuff here

			AppDomain.Unload(myDomain);

This code seems to work, but again... the file is not released - in this case, Toolkit_API.dll

I found this fixed bug on microsoft connect but dont know how to implement it.

			AppDomainSetup appSetup = new AppDomainSetup();

			appSetup.ApplicationName = "Toolkit_API";
			appSetup.ApplicationBase = Environment.CurrentDirectory;
			appSetup.LoaderOptimization = LoaderOptimization.SingleDomain;

			AppDomain myDomain = AppDomain.CreateDomain("Quigley");
			Assembly myAssembly = myDomain.Load("Toolkit_API");

			AppDomain.Unload(myDomain);

Tried this also, but it doesn't seem to release the lock.

Anyone know what im doing wrong?

Link to comment
Share on other sites

  • 0
No point making a new topic as this problem has the same symptoms.

I just found out yesterday that assemblies could not be unloaded from the program unless they are loaded into a separate AppDomain.

Once you are finish with the .dll file, you should be able to unload the AppDomain itself.

			AppDomain myDomain = AppDomain.CreateDomain("Quigley");
			Assembly myAssembly = myDomain.Load("Toolkit_API");

			// do stuff here

			AppDomain.Unload(myDomain);

This code seems to work, but again... the file is not released - in this case, Toolkit_API.dll

I found this fixed bug on microsoft connect but dont know how to implement it.

			AppDomainSetup appSetup = new AppDomainSetup();

			appSetup.ApplicationName = "Toolkit_API";
			appSetup.ApplicationBase = Environment.CurrentDirectory;
			appSetup.LoaderOptimization = LoaderOptimization.SingleDomain;

			AppDomain myDomain = AppDomain.CreateDomain("Quigley");
			Assembly myAssembly = myDomain.Load("Toolkit_API");

			AppDomain.Unload(myDomain);

Tried this also, but it doesn't seem to release the lock.

Anyone know what im doing wrong?

When you call CreateDomain, you have to pass the AppDomainSetup object into the method.

How do you know the lock isn't being released? What symptoms are you seeing?

Link to comment
Share on other sites

  • 0

AppDomain myDomain = AppDomain.CreateDomain("Quigley", null, appSetup);

oops... I was trying so many variations I must of posted the wrong example above.

The lock on .dll file is not being released once the appdomain is unloaded as i cannot manually delete the Toolkit_API.dll file on the system.

I am building an application which has a plugin framework. I want to be able to unload the plugin, delete it from the system and replace it with the latest version. At the moment I have to close the program to release the lock on the .dll files.

Link to comment
Share on other sites

  • 0
AppDomain myDomain = AppDomain.CreateDomain("Quigley", null, appSetup);

oops... I was trying so many variations I must of posted the wrong example above.

The lock on .dll file is not being released once the appdomain is unloaded as i cannot manually delete the Toolkit_API.dll file on the system.

I am building an application which has a plugin framework. I want to be able to unload the plugin, delete it from the system and replace it with the latest version. At the moment I have to close the program to release the lock on the .dll files.

Gotcha. When I try to delete, I get an UnauthorizedAccessException, so this may be a CAS problem. I'll investigate a little.

Link to comment
Share on other sites

  • 0
Gotcha. When I try to delete, I get an UnauthorizedAccessException, so this may be a CAS problem. I'll investigate a little.

Thanks man, really appreciate the help :)

Link to comment
Share on other sites

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.