Nehmen wir an, Sie haben ein .net-Objekt bufferObject
, das intern eine Art nicht verwalteten Speicherpuffer beträchtlicher Größe verwendet. Es ist so implementiert, dass es seinen zugewiesenen Speicher freigibt, wenn es entsorgt (oder finalisiert) wird.So binden Sie die Lebensdauer eines Objekts an die Lebensdauer eines anderen Objekts mit C#
Sie erstellen dann ein anderes Objekt reusingBufferObject
und es mit einem Zeiger auf die internen Puffer von bufferObject
liefern. Die beiden Objekte selbst kennen also die Existenz der anderen nicht.
Wenn bufferObject
den Gültigkeitsbereich verlässt und entsorgt/finalisiert wird, wird der interne Puffer freigegeben und reusingBufferObject
wird auf ungültigen Speicher zugreifen.
Natürlich kann das ganze Problem vermieden werden, indem Sie das Design der zugrunde liegenden Klasse der beiden Objekte ändern und reusingBufferObject
Referenz bufferObject
lassen. Nehmen wir an, dass beide Objekte von Drittanbieterklassen instanziiert werden und ihr Design nicht geändert werden kann.
Ein Beispielfall wäre die Verwendung einiger Bildverarbeitungsbibliotheken. Ein internes Bildobjekt müsste in ein Bitmap
Objekt umgewandelt werden, um es auf dem Bildschirm anzuzeigen, aber aus Leistungsgründen muss der interne Puffer des Bildobjektes vom Objekt Bitmap
wiederverwendet werden, anstatt nur dorthin kopiert zu werden.
Ist es möglich, die Lebensdauer von bufferObject
auf die Lebensdauer von reusingBufferObject
, zu binden, so dass es für die Garbage Collection qualifizierten bekommt erst nach reusingBufferObject
tut, ohne manuell den Überblick über die gesamte Lebensdauer zu halten?
EDIT:
Hier ein kurzes Beispiel, das Problem zu veranschaulichen:
namespace Example
{
// Some third party class with no control over its design.
// The Data property is the pointer to an unmanaged memory
// buffer.
public class ThirdPartyImage : IDisposable
{
public int Width { get; }
public int Height { get; }
public int Stride { get; }
public PixelFormat Format { get; }
public IntPtr Data { get; }
public ThirdPartyImage(string filename);
public Dispose();
}
public static class MyOwnExtensions
{
// Some method to reuse the internal memory buffer.
public static Bitmap ToBitmap(this ThirdPartyImage image)
{
return new Bitmap(image.Width, image.Height, image.Stride, image.Format,
image.Data);
}
}
class Program
{
static void Main(string[] args)
{
Bitmap bitmap = Foo();
// ThirdPartyImage is not referenced anymore and the internal buffer (Data)
// will be freed when garbage collected.
Bar(bitmap);
}
private static Bitmap Foo()
{
ThirdPartyImage image = ThirdPartyImage("foo.bmp");
Bitmap bitmap = image.ToBitmap();
return bitmap;
}
private static void Bar(Bitmap bitmap)
{
// Do some Bitmap related work here.
// The buffer could already be freed though.
}
}
}
EDIT:
Was ich suche ist so etwas wie eine Garbage Collection-Methode, dass können Sie die Lebensdauer eines Objekts mit einem anderen verknüpfen.
oder irgendeine Art von Benachrichtigung, wenn die reusingBufferObject
/Bitmap
gesammelt werden oder kommen für Sammlung bekommen, so dass ich einige automatisierten Mechanismus bauen kann ein Hilfsobjekt beteiligt, die bufferObject
und WeakReference
-reusingBufferObject
eine starke Referenz hält.
Die manuelle Verfolgung von zwei Objekten, von denen eines eigentlich nicht mehr benötigt wird (außer dem intern verwendeten Puffer), zB durch die Einführung einer Wrapper-Klasse, scheint mir einfach zu kompliziert zu sein.
Es hängt davon ab, welche Klasse 'bufferObject' leitet sich aus. Kannst du auch mehr Details über die beteiligten Arten im Allgemeinen geben? Die Metadatenansicht der Typen für "bufferObject" und "reusingBufferObject" wäre sehr nützlich. –
Es ist nicht möglich, diese Frage ohne weitere Details zu beantworten. Die genaue Semantik, wie die verschiedenen Objekte zugeordnet und zerstört werden, bestimmt, ob dies möglich ist oder nicht. – xxbbcc
Auch wenn 'bufferObject' nicht vor' reusingBufferObject' gesammelt wird, wie soll verhindert werden, dass 'bufferObject.Dispose()' aufgerufen wird? –