How to use BlockingCollection for image caching - c#

I'm hoping someone may please be able to assist me with a programming solution. I currently have a machine that acquires a bitmap image of an item on a conveyor. An image is acquired from the camera about every 5 seconds. I need to store (cache in memory) the most recent 4 images or so. Almost like a stack, where each time a new image is acquired, I need it at the top of the stack and it pushes the others down such that the last (oldest) image is dropped off. I was thinking of using a collection for storing these bitmaps. When I add the bitmap I will also add the unique "key" identifying the image. Since things need to run concurrently on this machine, I was thinking of using a BlockingCollection such that they run on their own thread using the producer-consumer method (from what I have researched). However, I have no experience with this and no idea how to get started.
After these images are taken and cached into my collection, the item moves down the conveyor a little more and then another image is taken of the same part with a different camera. An inspection is performed on this second image and if it is determined a "fail", I need to save this second image out to disk AND save the previous image of that same part (from the first camera). This is why I need to cache them and be able to retrieve them.
NOTE: The cameras are NOT next to one another such that the second image is acquired immediately after the first. Up to 2 or 3 parts may have gone past the first camera before they reach the second camera (as they go through a process in-between).
My idea is to
1). In my GUI thread I want to create an instance of a collection class to store the bitmap images and along with their unique keys. When an item is added to the collection the add method will determine the collection count and automatically remove the oldest one.
2). At certain instances (a "fail" at the second camera as described above) I will need to check/grab an image from the collection. I would like to use the TryTake method so that it will obtain the bitmap (based on the key that I provide) from the collection. I don't want the grabbing of the image from the collection to interfere with the possibly of adding one at the exact same moment.
3). Lastly, once I've obtained the image from the collection, I need to save that image out to disk along with the second image. I would like the save process to run on its own thread as well so that it doesn't impact performance or the ability of the app to need to work with the collection during a save process.
I have no idea how to get started on this except to make a class called cImageCache and add a property for the unique key. Any coding examples/help in either C# or VB.NET would be greatly appreciated! Thank you very much for your time.
Kindest Regards

I suggest using an ObjectCache. Come up with a key for the item, and store it. You can set it to be removed from the cache after a certain amount of time. It is threadsafe.

Related

WPF: Optimize loading time and memory usage of Canvas having 5000+ elements

As shown in the image above, my application has ~5000 elements drawn to a Canvas.
Due to this large number of elements, I've got two problems:
Memory usage is ~3 GB
The loading time is ~4 minutes
I need to optimize this.
E.g. as shown in the image, we are using combo box to bind item source 5000 with a list of string items.
Is there any way we can use the same items source location instead of creating new one every time for each one of the 5000 elements? That could solve the memory usage issue...
About the loading time, I don't worry so much now.
However, I currently have a progress bar which displays the loading progress of all those elements, but it does not work as expected (it closes before loading). I think it is so because we can't run two STA threads at the same time.
How can I keep this progress bar working until every element is successfully loaded to the canvas? I didn't find any event which informs the successful loading of elements to the canvas.
Any ideas on how to improve this application? Suggestions are welcome.

DisplayInformation in UWP Background Task

I want to access the DisplayInformation class from a background task in my UWP that takes an image and resizes it from its native resolution to the size of the user's screen, so that it can be set as a wallpaper.
However, when I attempt to use DisplayInformation.GetForCurrentView(), an exception is thrown, saying that the method must be called from a thread associated with a CoreWindow. How can I avoid this?
Any solution will work as long as it will give me the complete width and height of the user's screen in raw pixels.
This API requires a CoreWindow because you could have multiple monitors on your system, and it needs to know which one to pick (it picks the one that is currently showing the window). The best solution is to query the properties when your foreground app is running, and then save them for later use. (Of course this won't be perfect if the user has two or more monitors of different sizes and you pick the "wrong" one, or they upgrade the monitor, etc. but it's the best you can do).

.NET ImageList becomes corrupt occasionally

With a Winforms .net application, we have an issue where an image list occasionally becomes corrupted.
By corrupted I mean that the count of the number of images will be wrong and/or the images may have been replaced by system images (like dialog box icons).
For example, the screenshot below shows the imageInfoCollection showing the correct number, but the count showing the incorrect number.
The image list is on a form that is opened repeatedly by the user throughout the use of the application. The image list is used by a tab control on the form.
The issue occurs only occasionally, anywhere between every 5 and 20 times of opening the form.
The code to load the imagelist is built by the designer, and uses images from the resources:
this.imageListCallTakingScreen.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageListCallTakingScreen.ImageStream")));
this.imageListCallTakingScreen.TransparentColor = System.Drawing.Color.Transparent;
this.imageListCallTakingScreen.Images.SetKeyName(0, "spinner.png");
this.imageListCallTakingScreen.Images.SetKeyName(1, "recommendation-star.png");
this.imageListCallTakingScreen.Images.SetKeyName(2, "recommendation-star_red.png");
this.imageListCallTakingScreen.Images.SetKeyName(3, "recommendation-star - Transparent.png");
this.imageListCallTakingScreen.Images.SetKeyName(4, "Initialisation_fail16.png");
this.imageListCallTakingScreen.Images.SetKeyName(5, "information_white.png");
this.imageListCallTakingScreen.Images.SetKeyName(6, "Check-icon.png");
The imagelist isn't used anywhere other than in the designer.cs code to create it and wire it up to the tab control (except for the error trapping line I have put in):
Ideas? We are stuck on this one and google doesn't turn much up.
The imageInfoCollection field properly tracks the number of images you have in the ImageList. The Count property tracks the number of images that are actually present in the native Windows imagelist control.
There's only one way those values could have a mismatch that I can think of. Your program is leaking GDI object handles. A fairly common problem in Winform apps. That works for quite a while until you reach the operating system quota for such handles, after you've consumed 10,000 of them then Windows stops allowing you to create more. The error checking in the .NET wrapper class is not entirely kosher so this can happen without an exception getting generated. You'll see some more strange painting artifacts when you hit that limit btw.
You can get a basic diagnostic from Task Manager, Processes tab. Use View + Select columns and tick GDI Objects and USER objects. Observe these values while you operate the program like a user would. A steadily climbing value for GDI Objects spells doom. A hint that you are forgetting to use the using statement to dispose System.Drawing objects. And the garbage collector not running often enough to keep you out of trouble. You need to fix this in your code so the counter remains stable at, say, no more than several hundred objects.
A steadily climbing value for USER Objects is also a very common Winforms bug. That's a pretty fatal one, it will jack-up the GDI object count as well and the GC cannot fix this problem. This will happen when you remove controls in your code with Controls.Remove/At() or Controls.Clear() and forget to dispose the removed control objects.

High Volume, High Speed Textbox in .Net

I am writing an application that will display serial/USB data at a rate of up to 250kb/sec. I am using the .net SerialPort class and reacting to the DataReceived event. For early implementations of this software, I simply stored the incoming data in a WinForms RichTextBox. This solution works fine until there are 50k - 100k lines in the control, at which point the application bogs down. Since then, I've tried accomplishing my goals with WPF and found the same problem. I tried, at one point, to keep only the currently visible text in the textbox, and store the rest in a large List<string> but this solution required a huge number of workarounds and, in the end, was abandoned - I'd rather not reinvent the wheel.
Now I come to you for a thread of hope - I am willing to try anything! Should I use a custom control (both pay and free controls are welcome)? SQLite? Virtualization as described above? Should I try polling the SerialPort instead of reacting to events?
Use a thread to read the data and write it directly to a file. Have your app refresh the last x number of lines from the file every so often. Maybe even have the refresh based off of a notification from the reader thread?
By using multiple threads you'll keep the UI responsive and by writing straight to a file you'll ensure you've collected all of the data. Also, it will allow you to pause the display long enough to actually copy/paste the data you want while continuing to capture data.
Possibly you could implement your own type of file reader that would allow the user to "scroll" through the file by only loading the parts you can actually display on screen at one time.
If the data is largely line oriented (ReadLine) then put it in a ListBox. It is the fastest control for putting lots of text onscreen.
But you will find that all UI controls are geared toward human interaction, not to the speed of a Port. Best thing to do would be to rethink your design. What is that data for anyway?

How do i lock an asp.net page from multi-user editing?

i have a page with a series of checkboxes that authenticated users can change. I need to make this page only editable by one person at a time. So if a user goes into it and edits one of the checkboxes, noone else can go into the page and change other checkboxes.
I thought about an edit page link and a readonly page link (all controls disabled), then set a database flag if user enters under edit mode, but my concern is i wouldn't know if the user changed something, then just x'd out of the browser/app, locking everyone else out.
This is an internal app to company. Has anybody done something like this?
Any ideas or thoughts or suggestions?
Thanks
We have this functionality on an older ASP app. The user will load data with some type of primary key. We put in a DB entry to "lock" that page. If they correctly move through the site, it will unlock the resources at that time.
Other users opening this page will receive indication that the page is locked and a read-only version is rendered.
It would be fairly trivial to code a unPageUnload AJAX call to reset the lock for browser closing. We don't find this to be much of an issue and old locks are just cleared by an evening process if more than 4 hours old.
Our situation is where the pages are tied to specific regions of data. If this is a general config screen, I think a more dynamic AJAX solution that pushed the updates back and pings for changes might make sense. You would have to decide if you want to disable changes from others after the first update is received or implement collision detection for the data.
Some type of hashing of the page data would probably make this easier to detect changes.
You do what you said, but add a client side timer which will ping the server and tell you they are still there. If you don't get a ping within x mins you could let a new user go into edit mode but perhaps warn them (or not).
What about letting all users edit this page and how your script check in for page updates? Just like SO does, while you are typing in an answer, an orange message appears above saying "At least one new answer has been posted". You could display something like "The page has been modified since you last opened it".
There was something like timer in ASP.NET AJAX. You could use that to talk to the server to send "IN EDIT" status updates. You can even go further. Say you send "LOCKOUT REQUEST" requests every 15 seconds asynchronously and you expect to receive the "LOCKOUT GRANTED" response from server. If the response hasn't been received, you disable all controls on the page until maybe the next request receives the confirmation (the previous message could have been lost in the network). This way, if one user closes the browser, the other won't have to wait many minutes or hours until they get the edit permission.
Essentially, you need a distributed implementation for a critical section concept. It maube a challenge to implement it over HTTP. But that's a very interesting challenge, isn't it?
If you're trying to prevent two users from updating a db record and over-writing each other, perhaps it would be easier to detect this than prevent it.
On strategy for this is to include a "version" field in the record, and save that in a hidden field when rendering the page.
Then you simply include that as a condition of your update (i.e. UPDATE ... WHERE ID = myID AND VERSION = myversion) - if your update returns 0 rows, you know that someone else modified the data, and you can then decide what to do - reload the new data, offer the user a chance to compare them, etc.
How about an alternative to an extended lock?
Since you appear to be manipulating relatively small amounts of data, it would be more polite to put an encoded version of original state of the data in a hidden form field (or a datestamp, though that's less reliable; a hash of the values would work for larger amounts of data). In a transaction, check the state of the database against the hidden form values; if the original record has changed since the user submitted the changes, you reject the update. If not, accept the update, and commit the transacation.
Another approach could be to have an Application variable that contained a map or dictionary of locked items.
So, when one user hits edit, add an entry to the AppVariable Map or Dictionary, with the Key set to the primary ID of the field being edited. Then for all further requests, when they change between records, do a check of the ID within the map and if its being edited, Toggle off any update buttons. If you want to do it AJAXy, add a timer and an UpdatePanel and poll to see when the lock is released, then refresh the page with the updated data and enable the update buttons again.
Or, as a slightly greater UI, allow the users to edit while waiting for the lock to release ( the Map item to be removed ), then when it is removed, compare the fields they have been working on, with the updated database values and allow them to overwrite/merge their changes.
The only real downside is, 1) You would need to create one Application level Dictionary or Map for each table that you want to lock/unlock. 2) If you get into a webfarm environment, it breaks and you would have to use a different system.
Does that make sense?

Categories