FileFormatException loading tons of BitmapImages - c#

I am programming in C# and WPF and trying to load tons of images, but after about 5 seconds I'm getting Exceptions, which are not thrown directly (Visual Studio doesn't stop the program) and are logged as catched in Visual Studio.
My code looks like this:
public Dictionary<string, System.Windows.Media.Imaging.BitmapImage> images { get; private set; }
public MainWindow()
{
images = new Dictionary<string, System.Windows.Media.Imaging.BitmapImage>();
foreach (string file in Directory.GetFiles(#"C:\path\to\thumbnails"))
{
string id = Path.GetFileName(file);
id = id.Substring(0, id.Length - 4);
var image = new System.Windows.Media.Imaging.BitmapImage(new Uri(file));
image.Freeze();
images.Add(id, image);
}
InitializeComponent();
}
There are more than 8k jpg pictures in the folder, which are 44 x 64 pixels big. When running the program I see the Memory usage in Visual Studio and if there was an Exception. As mentioned before, the first 5 seconds or so are fine, but then I am getting an Exception with catch for every following picture I think. It's hard to tell because they are thrown too fast and Visual Studio displays them too slow, so they pop up in packs.
When the Exceptions start to show up, the Memory usage is rising very slowly compared to before, but if I let the program finish the loading all pictures can be displayed without problems. It also looks like Visual Studio is overwhelmed by the amount of Exceptions causing the Logger to be slower than real time. 1 second in Visual Studio seems to become 6 real time seconds and it's taking more than a minute of these "fake" seconds.
The Exception is the following (I am from Germany):
Ausnahme ausgelöst: 'System.IO.FileFormatException' in PresentationCore.dll ("Der Bitmap-Farbkontext ist ungültig.")
It looks like the picture is corrupted or has some errors, but I wasn't able to retrieve a filename and when I was, I tested the file seperately and it was okay.
I am just looking for a way to load all the images in normal speed.
Thanks in advance!
Update 1:
Somehow I disabled the "Just My Code" option in Visual Studio, causing to show exceptions outside my code and slowing Visual Studio down. Now it is running as fast as in the modification mentioned in the comments and takes about a minute to load all images.
I'm still wondering, if there is a way to load the images faster. All I am doing with them is displaying them.

Related

Release Memory After Loading Files

First off, I freely admit that I don't understand memory management very well, so I may be missing something obvious here. I've been looking through articles, etc. such as this, but haven't found anything helpful.
I'm looping through a collection of StorageFiles and creating a SlideTemplate for each one. (The SlideTemplate is just a UserControl containing an InkCanvas.) I'm then loading strokes into the InkCanvas from the file stream and adding the SlideTemplate to my ObservableCollection<SlideTemplate>. Here's the code:
foreach (var slide in slides)
{
using (var stream = await slide.OpenSequentialReadAsync())
{
InkCanvas inkCanvas = new InkCanvas();
SlideTemplate newSlide = new SlideTemplate();
await inkCanvas.InkPresenter.StrokeContainer.LoadAsync(stream);
newSlide.Set_Canvas(inkCanvas);
newSlide.Set_PenSize(new Size(DataModel.Instance.CurrentProject.PenSize, DataModel.Instance.CurrentProject.PenSize));
DataModel.Instance.CurrentProject.Slides.Add(newSlide);
}
}
When it gets to about number 61 or 62 it throws an exception on the "new InkCanvas()", saying that it "could not create instance of... InkCanvas." Here's the memory usage from the VS Diagnostic tools when it throws the exception:
The memory usage just keeps climbing as it loops through them. Putting this:
inkCanvas = null;
GC.Collect();
GC.WaitForPendingFinalizers();
in the foreach actually loads all eighty slides successfully, but once it's done the memory usage stays put and won't drop again. And then going back out (which uses a similar method to save the ink strokes back to the file) and reloading the project throws the same error using about 150MB of memory. Can someone please explain what's at play here, or link to a helpful article?

Does Microsoft ReportViewer require special handling to Dispose correctly?

I've spent the last day tracking down what seems to be a memory leak issue in my code, and believe I have finally pinned down the culprit - the report generation. In order to see where the problem lies I created an empty solution, with just a button on a blank form, linked to this event:
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 10000; i++)
{
Microsoft.Reporting.WinForms.ReportViewer temp = new Microsoft.Reporting.WinForms.ReportViewer();
temp.Dispose();
}
}
Opening this form and clicking the button, I watch Windows Task Manager and I can see the Memory begin climbing, along with the USER Objects, which in a matter of a minutes hits the cap of 10,000 and causes a WIN32Exception: Unable to create handle.
Debugging it line by line, you can see on creation the USER Objects goes up by 7, and then on Dispose it goes down by only 5.
I have tried temp.LocalReport.ReleaseSandboxAppDomain() based on other issues people were having, I've also tried the same loop but with using around the report viewer, to see if it behaved differently - it didn't.
My question is, is there any special handling around the ReportViewer that I am missing?
(FYI, I'm working on .NET Framework 4 with Microsoft.ReportViewer.WinForms version 10)

CPU is 100% at multithreading

First I've read all the posts here regarding this issue and I manged to progress a bit. However it seems I do need your help :)
I have a program with several threads, sometimes (not always) the CPU usage of the program is increasing up to 100% and never reduced until I shut down the program.
As I read in other similar posts, I ran the app using the visual studio (2012 - Ultimate).
I paused the app, and open the threads window.
There I pauses the threads until I've found the 4 threads which stuck the app.
The all refer to the same line of code (a call for constructor).
I checked the constructor inside and outside and couldn't find any loop which could cause it.
To be more careful I've added break point to almost every line of code and resume the app. None of them have been triggered.
This is the line of code:
public static void GenerateDefacementSensors(ICrawlerManager cm)
{
m_SensorsMap = new Dictionary<DefacementSensorType, DefacementSensor>();
// Create instance of all sensors
// For any new defacement sensor, don't forget to add an appropriate line here
// m_SensorsMap.add(DefacementSensorType.[Type], new [Type]Sensor())
try
{
if (m_SensorsMap.Count <= 0)
{
m_SensorsMap.Add(DefacementSensorType.BackgroundSensor, new BackgroundSensor());
m_SensorsMap.Add(DefacementSensorType.TaglinesSensor, new TaglinesSensor(cm.Database));
m_SensorsMap.Add(DefacementSensorType.SingleImageSensor, new SingleImageSensor());
}
}
catch (Exception)
{
Console.WriteLine("There was a problem initializing defacement sensors");
}
}
The second "m_SensorsMap.Add" is marked with green arrow, as I understand it, it means it's still waiting to the first line to finish.
By the way, the m_SensorsMap.Count value is 3.
How can I find the problem?
Is it a loop?
Or maybe a deadlock (not make sense because it shouldn't be 100% cpu, right?)
It's pointless to upload a code because this is a huge project.
I need more general help like how to debug?
Is it could something else than a loop?
Because it's a bug that returns every while and than I'm not closing the app until I found the problem :)
Thanks in advance!!
Edit:
The constructors:
public TaglinesSensor(IDatabase db)
{
m_DB = db;
}
I couldn't found the problem so I've changed the design on order not to call those constructors anymore.
Thanks for the guys who tried to help.
Shaul

foreach mysteriously hangs on first item of a ResourceSet

Occasionally our site slows down and the RAM usage goes up massively high. Then the app pool stops and I have to restart it. Then it's ok for a few days before the RAM suddenly spikes again and the app pool soon stops. The CPU isn't high.
Before the app pool stops I've noticed that one of our pages always hangs. The line it hangs on is a foreach on a ResourceSet :
var englishLocations = Lang.Countries.ResourceManager.GetResourceSet(new CultureInfo("en-GB"),true,true);
foreach(DictionaryEntry entry2 in englishLocations) // THIS LINE HANGS
We have the same code deployed on a different box and this doesn't happen. The main differences between the two boxes are :
Bad box
Window Server 2008 R2 Standard SP 1
IIS 7.5.7600.16385
.NET 4.5
24GB RAM
Good box
Window Server 2008 Server SP 2
IIS 7.0.6000.16386 SP 2
.NET 4.0
24GB RAM
I've tried adding uploadReadAheadSize="0" to the web.config as described here :
http://rionscode.wordpress.com/2013/03/11/resolving-controller-blocking-within-net-4-5-and-asp-net-mvc/
Which didn't work.
Why would foreach hang? It's hanging on the very first item, actually on the foreach.
Thanks.
I know it is an old post, but nevertheless... There is the potential of a deadlock when iterating over a ResourceSet and at the same time retrieving some other object through from the same Resources.
The problem is that when using a ResourceSet the iterator takes out locks on the internal resource cache of the ResourceReader http://referencesource.microsoft.com/#mscorlib/system/resources/resourcereader.cs,1389 and then in the method AllocateStringNameForIndex takes out a lock on the reader itself: http://referencesource.microsoft.com/#mscorlib/system/resources/resourcereader.cs,447
lock (_reader._resCache) {
key = _reader.AllocateStringForNameIndex(_currentName, out _dataPosition); // locks the reader
Getting an object takes out the same locks int the opposite order:
http://referencesource.microsoft.com/#mscorlib/system/resources/runtimeresourceset.cs,300
and http://referencesource.microsoft.com/#mscorlib/system/resources/runtimeresourceset.cs,335
lock(Reader) {
....
lock(_resCache) {
_resCache[key] = resLocation;
}
}
This can lead to a deadlock. We had this exact issue recently..
I experienced very similar problem.
Every once in a while IIS would hang, and I would see number of requests just sitting there. They were all in state ExecuteRequestHandler and with ManagedPipelineHandler module name.
After investigating with process explorer, I could see that all of them were sitting at mscorlib.dll!ResourceEnumerator.get_Entry, additional stack trace suggested some NGen action and then ntdll.dll!WaitForMultipleObjects.
My working hypothesis is that when multiple threads start enumerating those resources, we can run into a deadlock (possibly on some native code file generation), and alll subsequent threads then just keep on piling up.
To resolve it, I just created a critical section around this code block, to ensure that it is executed sequentially - I haven't experienced the issue since.
private static readonly object ResourceLock = new object();
public static MvcHtmlString SerializeGlobalResources(this HtmlHelper helper)
{
lock (ResourceLock)
{
// Existing code goes here ....
}
}
Based upon another answer to give you some idea how about using a try catch model ?
Perhaps it hangs because that resource isnt available / locked /..permissions etc.
var englishLocations = Lang.Countries.ResourceManager.GetResourceSet(new CultureInfo("en-GB"),true,true);
foreach(DictionaryEntry entry2 in englishLocations) // THIS LINE HANGS
ResourceManager CultureResourceManager = new ResourceManager("My.Language.Assembly", System.Reflection.Assembly.GetExecutingAssembly());
ResourceSet resourceSet = CultureResourceManager.GetResourceSet("sv-SE", true, true);
try { resourceSet.GetString("my_language_resource");}
catch (exception ex) { // from here log your error ex to wherever you like with some code }

How could the existence of pseudo debug strings cause a difference in functionality?

If I have these sprinkled throughout my code:
MessageBox.Show("See a format exception yet? #1");//todo: remove
(there are 7 of these, numbered from 1..7, most of which display (1,2,5,6,7))
I end up with one err msg ("Exception: Cannot find table 0 Location: frmFunction.SetPlatypus")
If I comment out all of those, I end up with a different err msg ("Exception: FormatException Location frmFunction.getDuckbillRecord")
How could this be? Shouldn't the existence/display of such an information msg have no effect on the way the code executes/the path it takes, etc.?
Note: getDuckbillRecord() is where all of the MessageBoxes are.
UPDATE
Using RT's suggestions as motivation, I came up with this:
public static StringBuilder LogMsgs = new StringBuilder();
public static void ExceptionHandler(Exception ex, string location)
{
try
{
LogMsgs.Append(string.Format("{0}\r\n", ex.Message)); //TODO: Comment out before deploying?
DateTime dt = DateTime.Now;
string timeAsStr = string.Format("{0}_{1}_{2}_{3}.txt", dt.Hour, dt.Minute, dt.Second, dt.Millisecond);
using (StreamWriter file = new StreamWriter(timeAsStr))
{
file.WriteLine(LogMsgs.ToString());
}
. . .
//in the problematic code, replacing the MessageBox.Show() calls:
TTBT.LogMsgs.Append("Made it to location 1 in frmOverFunction.GetDuckbillRecord()\r\n");
...and it did help - the exception is reached right after the first of 7 "code waypoints," so there's something rotten in that particular Denmark, apparently.
UPDATE 2
After the rare experience of being able to run the app without crashing somewhere, I realized I also need that file-writing code in the main form's OnClosing() event - being in the global exception handler had worked for awhile - I wasn't expecting a clean termination of the app to ever occur again, I guess.
I'd strongly encourage you NOT to use MessageBox.Show(...) to log/trace/debug errors, because popping-up a dialog can introduce many subtle bugs and changes in behavior, focus, etc., especially if your UI flow/state is important.
Instead, use System.Diagnostics.Trace for writing tracing code (which you can optionally compile into your production/release code) or System.Diagnostics.Debug to write debug messages which get removed when you build your release version.
For example:
public void DoSomething(int a, int b)
{
Trace.TraceInformation("Starting to do something: a = {0}, b = {1}",
a, b);
try
{
int c = a / b;
}
catch (DivideByZeroException e)
{
Debug.WriteLine("OH NO ... 'b' WAS ZERO!!!! RUN AWAY!!!!");
throw e;
}
Trace.TraceInformation("Done doing something");
}
In the example above, the debug output will be available in debug builds, but will be removed in release builds. Trace output will be available in debug and retail bugs (unless you turn off the TRACE build parameter) but introduces no measurable perf impact unless you hook-up a listener and start writing trace output to a slow medium like spinning disks, ticker-tape printers, etc. ;)
When you run code with Trace and/or Debug builds with Debug messages in Visual Studio, the messages are written to the Output pane so you can watch what's going on inside your app as it runs.
If you want to, you can also write a stand-alone trace listener that listens for Trace and/or Debug messages and log them to a file/database or display them in a console window (or GUI if you want to get fancy).
You can also use tools like log4net which enables you to write log/trace messages to a variety of file formats, databases, etc.

Categories

Resources