Laden...

Image laden ohne File zu blockieren

Erstellt von Stefan.Haegele vor 6 Jahren Letzter Beitrag vor 6 Jahren 1.789 Views
Stefan.Haegele Themenstarter:in
463 Beiträge seit 2009
vor 6 Jahren
Image laden ohne File zu blockieren

Hallo zusammen,

eigentlich eine ganz einfache Aufgabe:

Ich möchte ein Image aus einem File laden, ohne das File selbst zu blockieren. Laut Google sollte es mit folgenden Code funktionieren:


using (FileStream stream = new FileStream(value, FileMode.Open, FileAccess.Read))
{

    this.gdi_Image = Image.FromStream(stream);
                        
}

Funktioniert auch wunderbar - leider nicht nicht auf Windows Server 2003 R2. Leider muss ein Microservice des Programms darauf laufen. Auch die Erweiterung:


using (FileStream stream = new FileStream(value, FileMode.Open, FileAccess.Read))
{

   Image image = Image.FromStream(stream);
   this.gdi_Image = (Image)image.Clone()
                     
}

bringt/brachte keinen Erfolg. Laut MSDN sollte der FileStream bis zum Ende bestehen bleiben, jedoch bleibt dann das File auch wieder gesperrt.

Es kann doch nicht sein, dass es für so eine einfache Aufgabe keine Lösung gibt? Oder stelle ich mich nur dumm an oder sehe aktuell vor lauter Bäume den Wald nicht...

Die Exception "Nicht genügend Arbeitsspeicher" ist laut google in diesem Fall auch sehr undeutlich. Es sind zum Zeitpunkt des Erstellens noch ca. 3 GB frei... Und wie man sieht, wird ein Teil der Images angezeigt.

Viele Grüße
Stefan

T
2.222 Beiträge seit 2008
vor 6 Jahren

Klingt danach als würdest du deine Bilder nicht mehr freigeben, weshalb deinem Server der RAM ausgeht.
Deine Bilder müssen, wenn du diese nicht mehr brauchst, auch per Dispose wieder freigeben werden.
Hier musst du also deine Bilder sauber freigeben, dann sollte sich das Problem lösen.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.827 Beiträge seit 2008
vor 6 Jahren

Ein Stream muss offen bleiben, damit er vom Image genutzt werden kann.

You must keep the stream open for the lifetime of the Image.

Beide Deiner Varianten halten ein Stream auf das Image. Da hilft auch ein Clone nicht.
Schau Dir dazu an, wie Clone funktioniert, dann verstehst Du es.

Lösung: kopiere (nicht referenziere!) den Inhalt vom FIleStream in einen MemoryStream.
Schließe den FileStream.
Erstelle ein Image aus dem MemoryStream.
Sofern das Image an ein Control refernziert wird - wie hier - dann kümmert sich i.d.R. das Control um das korrekte Disposen.

OutOfMemoryException hat nicht unbedingt was mit dem Arbeitsspeicher zutun.
Die Exception - siehe Erklärung in der MSDN - kann auch geworfen werden, wenn Dir zB. die Systemhandles - z.B. durch zu viele offene Streams - ausgehen.

Stefan.Haegele Themenstarter:in
463 Beiträge seit 2009
vor 6 Jahren

Vielen Dank für den Schubser in die richtige Richtung. Ich habe die Funktionnun folgendermaßen angepasst (da auf dem Server nur .net V3.5 vorhanden ist die Instalation von V4.x nicht freigegeben wurde):


try
{

	byte[] buffer = new byte[16384];
	
	using (FileStream file = new FileStream(value, FileMode.Open, FileAccess.Read))
	{

		int read;

		MemoryStream memory = new MemoryStream();

		while ((read = file.Read(buffer, 0x00, buffer.Length)) > 0x00)
		{
			
			memory.Write(buffer, 0, read);
		
		}

		this.gdi_Image = Image.FromStream(memory);
		
	}
}
catch (Exception exp)
{

	EXC.LogException(exp, ExErr.GFX_NoLoad);

}

3.003 Beiträge seit 2006
vor 6 Jahren

Etwas sauberer mit CopyTo/CopyToAsync.

EDIT: my bad. Framework 3.5.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

D
985 Beiträge seit 2014
vor 6 Jahren

var content = file.ToArray();
var memory = new MemoryStream( content );

würde auch unter .net 3.5 funktionieren.

Ist kürzer und darum übersichtlicher, muss aber nicht zwangsläufig besser sein. Auslagern würde ich den Code zum Kopieren des Stream-Inhalts aber auf jeden Fall.