Do not dispose objects multiple times - memory-management

Can't seem to see why FXCop is complaining that I am disposing the memoryStream object more than once. As near as I can tell, I'm only disposing of it in the finally block.
Full error message is:
CA2202 Do not dispose objects multiple times Object 'memoryStream' can be disposed more than once in method 'MessageTransform.GetEnvelope(Message)'. To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object.: Lines: 48 Api MessageTransform.cs 48
var memoryStream = new MemoryStream();
try
{
var messageBuffer = message.CreateBufferedCopy(int.MaxValue);
var xPathNavigator = messageBuffer.CreateNavigator();
var xmlWriter = XmlWriter.Create(memoryStream);
xPathNavigator.WriteSubtree(xmlWriter);
xmlWriter.Flush();
xmlWriter.Close();
memoryStream.Position = 0;
var xdoc = XDocument.Load(XmlReader.Create(memoryStream));
return xdoc;
}
catch (ApplicationException e)
{
Console.WriteLine(e.Message);
return null;
}
finally
{
memoryStream.Dispose();
}
If I wrap the same code in a using block I get the same error.
using (var memoryStream = new MemoryStream())
{
var messageBuffer = message.CreateBufferedCopy(int.MaxValue);
var xPathNavigator = messageBuffer.CreateNavigator();
var xmlWriter = XmlWriter.Create(memoryStream);
xPathNavigator.WriteSubtree(xmlWriter);
xmlWriter.Flush();
xmlWriter.Close();
memoryStream.Position = 0;
var xdoc = XDocument.Load(XmlReader.Create(memoryStream));
return xdoc;
}
Is this just an issue with a hyperactive FXCop or does using a using block or .Dispose() somehow not apply to a System.IO.MemoryStream?

The XmlWriter can dispose the stream from its Close method, which is what the rule is picking up. However, this behavior is conditional and should not be invoked in an XmlWriter created for a stream in the way you describe.

As Nicole described, the XmlWriters' Close can dispose the Memorystream-object, which is causing the error to be raised.
I do want to point out that a using statement and try-finallystatement are the exact same thing. The compiler translates using statements into a tryblock with your execution and a Dispose() in the finallyblock.

Related

Issue scaling the first page of a PDF using iText7 for .NET

I'm trying to scale the first page of a PDF using iText7 for .NET. The rest of the pages should remain untouched.
The method below works if the PDF contains one page, but if there's multiple pages, the first (supposed to be scaled) page is blank, while the remaining pages is added correctly.
What am I missing here?
public byte[] ScaleFirstPagePdf(byte[] pdf)
{
using (var inputStream = new MemoryStream(pdf))
using (var outputStream = new MemoryStream(pdf))
using (var srcPdf = new PdfDocument(new PdfReader(inputStream)))
using (var destPdf = new PdfDocument(new PdfWriter(outputStream)))
{
for (int pageNum = 1; pageNum <= srcPdf.GetNumberOfPages(); pageNum++)
{
var srcPage = srcPdf.GetPage(pageNum);
var srcPageSize = srcPage.GetPageSizeWithRotation();
if (pageNum == 1)
{
var destPage = destPdf.AddNewPage(new PageSize(srcPageSize));
var canvas = new PdfCanvas(destPage);
var transformMatrix = AffineTransform.GetScaleInstance(0.5f, 0.5f);
canvas.ConcatMatrix(transformMatrix);
var pageCopy = srcPage.CopyAsFormXObject(destPdf);
canvas.AddXObject(pageCopy, 0, 0);
}
else
{
destPdf.AddPage(srcPage.CopyTo(destPdf));
}
}
destPdf.Close();
srcPdf.Close();
return outputStream.ToArray();
}
}
I couldn't reproduce the blank page issue with this code, but definitely the files that are generated in this way can be problematic.
The issue is that you are sharing a byte buffer between two memory streams - one used for reading and another one for writing, simultaneously.
Simply using another buffer or relying on the default MemoryStream implementation solved the issue for me, and should do so for you as well because there doesn't seem to be anything suspicious about your code apart from the problem I mentioned.
Here is how you should create the output stream:
using (var inputStream = new MemoryStream(pdf))
using (var outputStream = new MemoryStream())
If you still experience issues even after this tweak then the problem is definitely file-specific and I doubt you could get any help without sharing the file.

AVCapturePhotoSettings not accepting accept NSDictionary element

not sure what I am doing wrong, I wanna create a simple custom camera, I'm creating the AVCapturePhotoOutput attaching it to AVCaptureSession, then creating AVCapturePhotoSettings with minimum settings to make taking a picture work, see code below.
I get exception kCVPixelBufferPixelFormatTypeKey is not being define but it is indeed in the NSDictionary I am passing.
I need some light here, thanks
public void TakePicture()
{
var output = new AVCapturePhotoOutput();
_captureSession.AddOutput(output);
var settings = AVCapturePhotoSettings.Create();
var previewPixelType = settings.AvailablePreviewPhotoPixelFormatTypes.First();
var keys = new[]
{
new NSString("kCVPixelBufferPixelFormatTypeKey"),
new NSString("kCVPixelBufferWidthKey"),
new NSString("kCVPixelBufferHeightKey"),
};
var objects = new NSObject[]
{
// don't have to be strings... can be any NSObject.
previewPixelType,
new NSString("160"),
new NSString("160")
};
var dicionary = new NSDictionary<NSString, NSObject>(keys, objects);
settings.PreviewPhotoFormat = dicionary;
output.CapturePhoto(settings,this);
}
It is because kCVPixelBufferPixelFormatTypeKey is not available in Xamarin.
We should use CVPixelBuffer.PixelFormatTypeKey here . It will be convert to kCVPixelBufferPixelFormatTypeKey automatically when compiling.
The same reason for kCVPixelBufferWidthKey and kCVPixelBufferHeightKey , the api is CVPixelBuffer.WidthKey and CVPixelBuffer.HeightKey in Xamarin.iOS.

iTextSharp : Cannot attach PageEvent on a PdfSmartCopy writer

This code using ItextSharp 5.5.10:
var msOutput = new MemoryStream();
var document = new Document(PageSize.A4, 0, 0, 0, 20);
var writer = new PdfSmartCopy(document, msOutput);
writer.PageEvent = new MyHeaderFooterEvents();
Throws "Operation is not valid due to the current state of the object." when assigning the "writer.PageEvent" (also fails when doing a parameterless new Document()).
When this code works perfectly:
var outputStream = new MemoryStream();
var document = new Document(PageSize.A4, leftMargin, rightMargin, topMargin, bottomMargin);
var writer = PdfWriter.GetInstance(document, outputStream);
writer.PageEvent = new MyHeaderFooterEvents();
Any idea ?
The Pdf[Smart]Copy classes are intended for read-only usage. It's documented in the raw source code:
/// Setting page events isn't possible with Pdf(Smart)Copy.
/// Use the PageStamp class if you want to add content to copied pages.
Note to the iText development team - if XML Documentation Comments using the <summary> tag are used instead of the current style, comments will show up in Visual Studio IntelliSense.

MediaLibrary.SavePicture method results in a System.UnauthorizedAccessException

I've got the following code which handles downloading and saving an Image to the phone's media library. It fails with a System.UnauthorizedAccessException as if there was some cross-thread access. To my understading all code below an await statement runs on the UI thread so this should not be an issue. In addition I've tried wrapping the code below var stream = await client.OpenReadTaskAsync(this.Url); with Deployment.Current.Dispatcher.BeginInvoke but it did not help. :(
I am running this on WP8 with the intention to port the code later to WP7.
private async void OnSaveImageCommand()
{
RunProgressIndicator(true, "Downloading image...");
var client = new WebClient();
try
{
var stream = await client.OpenReadTaskAsync(this.Url);
var bitmap = new BitmapImage();
bitmap.SetSource(stream);
using (var memoryStream = new MemoryStream())
{
var writeableBitmap = new WriteableBitmap(bitmap);
writeableBitmap.SaveJpeg(memoryStream, writeableBitmap.PixelWidth, writeableBitmap.PixelHeight, 0,
100);
memoryStream.SetLength(memoryStream.Position);
memoryStream.Seek(0, SeekOrigin.Begin);
var mediaLibrary = new MediaLibrary();
mediaLibrary.SavePicture("image.jpg", memoryStream);
MessageBox.Show("Image has been saved to the phone's photo album");
}
}
catch
{
MessageBox.Show("Failed to download image");
}
finally
{
RunProgressIndicator(false);
}
}
Did you add an ID_CAP_MEDIALIB_PHOTO capability to your app's manifest?
UnauthorizedAccessException is 99% of the time a missing capability.

How do I close an OracleConnection in .NET

Say I have these two objects:
OracleConnection connection = new OracleConnection(connectionString);
OracleCommand command = new OracleCommand(sql, connection);
To close the connection or Oracle, do I have to call command.Dispose(), connection.Dispose(), or both?
Is this good enough:
using(connection)
{
OracleDataReader reader = cmd.ExecuteReader();
// whatever...
}
using (OracleConnection connection = new OracleConnection(connectionString))
{
using (OracleCommand command = new OracleCommand(sql, connection))
{
using (OracleDataReader reader = cmd.ExecuteReader())
{
}
}
}
If it implements IDisposable, and if you create it, then put it in a using block.
Both answers are pretty much on target. You always want to call .Dispose() on any IDisposeable object. By wrapping in a "using" you tall the compiler to always impliment a try/finialy block for you.
1 point of note, if you want to avoid the nesting, you can write the same code like this:
using (OracleConnection connection = new OracleConnection(connectionString))
using (OracleCommand command = new OracleCommand(sql, connection))
using (OracleDataReader reader = cmd.ExecuteReader())
{
// do something here
}
This is good enough. using statement will wrap the dispose statement, so even if the exception is thrown, you are safe, it's my preferred way to dispose the resource.
using(OracleConnection connection = new OracleConnection(connectionString); )
{
//Create a command object
using(OracleCommand command = new OracleCommand(sql, connection))
{
using(OracleDataReader reader = cmd.ExecuteReader())
{
}
}
// whatever...
}
I think by use "using", you are ask the compiler to inject a try ... finally block , and in finally block, it will close the disposable object for you.
using will ensure your connection is closed. You could also pass in CommandBehavior.CloseConnection to your command's ExecuteReader method to close it before Dispose is called.

Resources