I'm using the following code to read some cached images from an IsolatedStorageFile:
using (IsolatedStorageFile storageFile = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = storageFile.OpenFile(filename, FileMode.Open, FileAccess.Read))
{
BitmapImage result = new BitmapImage();
result.SetSource(stream);
return result;
}
}
From time to time I get the following exception:
The detail has the following text:
Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection
Any ideas? I don't know if this matters but this code is accessed in a heavy multithreaded environment (I mean that there are a lot of threads calling these lines).
I know this is a first chance exception but anyway I don't get the reason.
I have encountered the same error with very similar code. in my experience it only happens on a corrupt photo file. the photos are all generated by the CameraCaptureTask and i have never been able to reproduce the error, but it happens in the wild.
the error message is a bit misleading.
i'm explicitly calling Close+Dispose on the filestream but that is equivalent to the "using" declarations, ignacio is correct in his reply above.
Remove the second using statement for stream object which will fix the issue.
Related
I am saving images on the server and I am covering the scenario where the disk has no available free space. To simulate that, I created an almost-no-space virtual hard drive and I am trying to save the images there.
I was expecting to receive an exception when trying to save the image, with:
using (var ms = new MemoryStream(myPictureStream))
using (Image image = Image.FromStream(ms))
{
image.Save(fileName, ImageFormat.Jpeg);
}
But that is not the case, there is no exception thrown. Instead, an empty file is saved, so I can not be aware of the error.
I would like to receive some error when trying to save the image, or being able to anticipate the error before an exception is thrown.
I already considered some possible solutions:
I know I can check the available free space on a drive with DriveInfo, but I will not have the drive letter to check that on production, so this option is discarded.
After saving the image, I try to retrieve it with Image.FromFile and then an OutOfMemoryException is thrown, but I know that this can happen in other scenarios, and I am not sure if this is a legitimate way of checking that the disk has no free space.
So... Any idea why Image.Save() does not throw errors when no free space available? Any suggestion on how to handle this scenario?
EDIT
GetLastError does not help (it is code 0, success), so it seems that the best way to handle this scenario is saving the image to a temporal MemoryStream and then writing it into a file, as pointed out by answers given by #Eldar and #nvoigt.
Doing it this way, a IOException is thrown, and you can check the HResult of the exception to see if it is a not-enough-free-space-in-disk easy (see this answer: https://stackoverflow.com/a/9294382/4067893).
Image.Save() internally calls a GDI function GdipSaveImageToFile() that doesn't fail if the drive space is insufficient. You may give a try to GetLastError() to get the last Win32 error.
If GetLastError() doesn't help, the only solution that comes up in my mind is saving the image to a temporal MemoryStream, then writing the resulting stream into a file.
You will need to do the stream handling yourself:
using (var ms = new MemoryStream(myPictureStream))
using (Image image = Image.FromStream(ms))
using(var jpg = new MemoryStream())
using (var file = new FileStream(fileName, FileMode.Create, FileAccess.Write))
{
image.Save(jpg, ImageFormat.Jpeg);
jpg.Seek(0, SeekOrigin.Begin);
jpg.WriteTo(file);
}
I have 2 pieces of sample codes, I try to do the same thing that update property items back to image and save it under a different file.
Code 1
Image image;
using (FileStream stream = new FileStream(this.fileName, FileMode.Open)) {
image = Image.FromStream(stream);
foreach (var property in this.propItems) {
image.SetPropertyItem(property);
}
}
image.Save(#"D:\Temp\1.jpg");
image.Dispose();
Code 2
using (Image image = new Bitmap(this.fileName)) {
foreach (var property in this.propItems) {
image.SetPropertyItem(property);
}
image.Save(#"D:\Temp\1.jpg");
}
The only difference is that how I opened the file. If I run the first piece of code I got exception message
System.Runtime.InteropServices.ExternalException was unhandled
HResult=-2147467259 Message=A generic error occurred in GDI+.
Source=System.Drawing ErrorCode=-2147467259
My 2nd piece of code just runs fine, I can get proper output. What is the difference here?
This is by design, the MSDN article for Image.FromStream() sternly warns about this. Once you close the stream, the image is no longer usable. And trying to save it like you do is very likely, but not guaranteed, to throw an exception when it tries to retrieve pixel data from a closed stream.
A key property of the Image class is that it is lazy, not unlike many .NET classes, it won't access the stream data until necessary. And it isn't necessary until the pixel data is actually used, that happens in the Save() call in your snippet. Kaboom when it can no longer read it.
You can fix your first snippet by moving the Save() call inside the using statement:
using (var stream = new FileStream(this.fileName, FileMode.Open))
using (var image = Image.FromStream(stream) {
foreach (var property in this.propItems) {
image.SetPropertyItem(property);
}
image.Save(#"D:\Temp\1.jpg");
}
No point in using a FileStream anymore. Do note that the file that you save the image to cannot be the same file that you read the image from. Some hint that you tried to work around that problem. Using a MemoryStream is a common technique to avoid the lock on the file.
Also note another bug in your code, you save the file with the .jpg extension but it is actually a PNG. You cannot omit the ImageFormat argument if you want a JPEG.
This question already has answers here:
IOException: The process cannot access the file 'file path' because it is being used by another process
(12 answers)
Closed 2 years ago.
EDIT: I finally found the error. It is totally irrelevant with the bitmaps or streams or static. It appears that one of my colleagues has forgotten to remove email attachment after sending the mail, and the mail attachment service keeps open. I used a using statement for whole mail sending process, and it is solved. Thanks everyone.
I know you might say that there are billions of threads with the same title and this is a duplicate, but believe me it is not. I have been searching for the solution like 7 hours, but nothing helped so far.
The problem is the following: This is a photo capture application which uses WebcamSource as the webcam. The application runs well when first photo is taken and emailed to user. However, when user returns to the process all over again (where it started before the first run), application gives such a error. The erroneous code is below.
public static void SaveImageCapture(BitmapSource bitmap)
{
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
// bitmap = BitmapFrame.Create(BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
encoder.Frames.Add(BitmapFrame.Create(bitmap));
encoder.QualityLevel = 100;
encoder.Rotation = Rotation.Rotate270;
try
{
using (FileStream fstream = new FileStream("Photos\\" + fileName + ".jpg", FileMode.Create))
{
encoder.Save(fstream);
fstream.Close();
}
}
catch (Exception e) {
System.Windows.Forms.MessageBox.Show(e.ToString());
}
}
Code crashes at FileStream fstream = new FileStream("Photos\\" + fileName + ".jpg", FileMode.Create) and it gives the error
The process cannot access the fileĀ "C:\Users[username]\Dropbox[projectname][projectname]\bin\Debug\Photos" because it is being used by another process.
I tried closing webcam stream, surrounding the code with try/catch, putting it into using statement, adding FileAccess and FileShare fields, trying to add BitmapCreateOptions.None and BitmapCacheOption.OnLoad(it did not allow me), creating new images with different names rather than overwriting the same image, deleting image after sending email(it gave me the same error), and some small arrangements that may cause file access problems.
I would suggest making the filename something more generic so appending a timestamp or something, but additionally, in the using call fstream.Flush() before fstream.Close()
Do you reference that file location (Mainly the Photos folder) anywhere else in your code before it reaches this point?
It seems like you have accessed this elsewhere in your code and the connection to it has not been closed off - it's handy to use the Using block whenever calling IO methods.
Although it's not ideal, try to call GC.Collect() after encoder.Rotation = Rotation.Rotate270;
I am having problem with saving of my object. Take a look at this code:
public void SerializeToXML(String FileName)
{
XmlSerializer fSerializer = new XmlSerializer(typeof(Configuration));
using (Stream fStream = new FileStream(FileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
fSerializer.Serialize(fStream, this);
}
}
The problem is that when the user does not have rights to the location on hard disk, this function will not throw me any exception and do not save my file. For example saving to "C:\test.xml" act like nothing happened. And I would like to know if the file has not been saved and it would be good to know the reason why.
I know that I could check if the file on given location exists and throw an exception manualy but shouldn't this be done by the XmlSerializer or FileStream itself?
Thanks for your time
Edit:
As I was suspecting I had to turn on some additional debugging. Since I am using the using clause, the "Enable unmanaged code debugging option" must be check in project properties under the Debug section. After this, the exception is shown in the debugging process.
Edit2
Replacing the above using clause with this code triggers the exception:
public void SerializeToXML(String FileName)
{
XmlSerializer fSerializer = new XmlSerializer(typeof(Configuration));
Stream fStream = new FileStream(FileName, FileMode.Create, FileAccess.Write, FileShare.None);
try
{
fSerializer.Serialize(fStream, this);
}
finally
{
fStream.Close();
}
}
That sounds very strange to me - and it doesn't sound like it has anything to do with the serializer. If you don't have access rights to a particular location, then creating the FileStream should throw an exception; it shouldn't wait until the Serialize line.
Are you absolutely sure that you don't have some catch block higher up which is hiding the problem from you?
I suspect that it has to do with your using statement, because it uses a hidden try-finally construction (where the Dispose() method is called in the finally clause). Information about exceptions which are not visible outside the using block can be found here.
Try replacing the using statement by an instantiation and a call to it's Dispose() method, and I think your problem is solved. Of course, you should afterwards enclose your code in an explicit try-finally structure as part of good programming practice.
Vista file redirection can explain this. It is a feature to allow legacy programs that don't handle UAC properly to still operate. The file gets redirected to the virtual store.
This will happen when you use Visual Studio 2005 or earlier or did something to prevent the manifest from getting embedded in the exe. Fix it by including a manifest.
I've found the common way to get image metadata in WPF is to create a BitmapFrame object and inspect the Metadata property on it. However I can't seem to create a BitmapFrame object that fulfills these two requirements:
Does not lock the file
Does not throw weird, undocumented exceptions when given certain files
Using these lines seems to create the BitmapImage reliably:
BitmapFrame.Create(new Uri(imageName));
BitmapFrame.Create(new Uri(imageName), BitmapCreateOptions.DelayCreation, BitmapCacheOption.None);
However they leave the file locked for an indeterminate amount of time. There is no dispose method on the BitmapFrame as far as I can tell.
This keeps the file from being locked:
BitmapFrame.Create(new Uri(imageName), BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
However on Vista it throws ArgumentExceptions and InvalidOperationExceptions on certain files and on Win7 it throws FileFormatExceptions and IOExceptions. This makes me think that caching the BitmapFrame is unsupported/untested.
Can you get metadata from an image in WPF without leaving a lock on the file for an indeterminate length of time?
Have you tried using a converter approach? For example, my Intuipic application does this. See BitmapFrameConverter for details on loading without locking, and BitmapOrientationConverter for getting at metadata.
I don't know if an answer at this time can still be useful to anybody but since I got here only today, I assume that somebody else may be interested.
I had a similar problem when trying to use BitmapFrame to test if an image is valid, then trying to rename the image file. With this code, the image is locked and the Move command does not work:
bool isImageValid = true;
try
{
BitmapFrame bmpFrame = BitmapFrame.Create(new Uri("C:\\Images\\Test.jpg"));
}
catch
{
isImageValid = false;
}
File.Move("C:\\Images\\Test.jpg", "C:\\Images\\Test0.jpg");
However, when I first read the image file in a file stream, the file is released as soon as the using block is done and the Move command works:
bool isImageValid = true;
try
{
using (FileStream fs = new FileStream("C:\\Images\\Test.jpg", FileMode.Open))
{
BitmapFrame bmpFrame = BitmapFrame.Create(fs);
}
}
catch
{
isImageValid = false;
}
File.Move("C:\\Images\\Test.jpg", "C:\\Images\\Test0.jpg");
Try either bitmapImage.StreamSource.Dispose() or bitmapImage.Freeze();