Avoid memory leak for IDisposable/NonShared exports
See original GitHub issueConsider the sample below. When the exported type implements IDisposable
the container keeps a reference to all created values, even if they are non-shared. This easily causes significant memory leaks.
What is the recommended pattern here?
using System;
using System.ComponentModel.Composition;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.VisualStudio.Composition;
using CreationPolicy = System.ComponentModel.Composition.CreationPolicy;
namespace MefTest
{
[Export(typeof(ViewModel)), PartCreationPolicy(CreationPolicy.NonShared)]
public class ViewModel : IDisposable
{
private byte[] bytes;
public ViewModel() => bytes = new byte[100000]; // Leak
public void Dispose() {}
}
class Program
{
static void Main(string[] args)
{
var t = InitMef();
t.Wait();
var container = t.Result;
for (var i = 0; i < 100; i++)
{
var model = container.GetExportedValue<ViewModel>();
model.Dispose(); // Container keeps a reference here!
}
// NOTE: I want to keep my container.
// How do I release the memory allocated above?
// container.Dispose();
}
private static async Task<ExportProvider> InitMef()
{
var discovery = PartDiscovery.Combine(new AttributedPartDiscoveryV1(Resolver.DefaultInstance));
var catalog = ComposableCatalog.Create(Resolver.DefaultInstance)
.AddParts(await discovery.CreatePartsAsync(Assembly.GetExecutingAssembly()))
.WithCompositionService();
var config = CompositionConfiguration.Create(catalog);
var epf = config.CreateExportProviderFactory();
var exportProvider = epf.CreateExportProvider();
return exportProvider;
}
}
}
Issue Analytics
- State:
- Created 4 years ago
- Reactions:2
- Comments:9 (7 by maintainers)
Top Results From Across the Web
Avoid Memory Leaks with Third-Party Libraries
In this article, you will learn how to avoid memory leaks when using third-party libraries or frameworks in embedded software projects, by following...
Read more >How can I handle the memory leakage problems?
The very best way to handle the memory leakage problem is to develop patience. ... If for example you do an export using...
Read more >Memory leak involving a class exported from a DLL
I read this excellent article by Eli Bendersky on exporting C++ classes from a DLL. I want to make a class that creates...
Read more >9 ways to avoid memory leaks in Android | by Anitaa Murthy
There are a lot of articles on memory leaks and how to fix them. ... How to solve this? Option 1: Cancel timer...
Read more >Preventing and Debugging Memory Leaks in Node.js
Learn about Node.js memory leaks and their causes, how to debug and fix them, prevention best practices, methods for monitoring leaks.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Yes, it’s by design that the container maintains references to disposable values. But once a NonShared disposable value has been disposed of by itself, I believe there’s no reason for the container to retain its reference.
I imagine the
ExportLifetimeContext<T>
orExport<T>
Dispose()
method should not only dispose theT
value but remove the reference from the container.But now that I look at your code a bit more, I see you don’t have either of those wrappers, since you’re calling
GetExportedValue<T>
so all you get back is aT
. So in fact this “leak” may in fact be by design. We’ll have to review.In the meantime, can you try using an
ExportFactory<T>
instead to create the instances you need? That will give you the wrapper, and that wrapper may already release the container’s reference when you dispose the value.I’m taking a look at this now.