I use a DataGridView to monitor IO events. Each time a new IO event occurs, the DataGridView is populated with a new item containing a timestamp among other data. These updates come every 10 ms, and I want to place the new items at the top of the grid.
I only need to keep ~100 rows in the grid; the older ones should be discarded as to not consume memory. All my attempts have proven to be too slow, do you have any ideas on how to approach this?
Displaying ticking data is quite challenging task. One of the biggest step to improve performance can be reducing refresh rate to a number recognizable by human eye - 20 refreshes per second without reacting to each and every IO event.
Create or use a ring buffer to store 100 records only and reduce GC / memory.
Use Dispatcher timer and schedule a grid refresh every 50ms. At the timer tick, grab the buffer data into the preallocated collection and refresh the Grid entirely.
You can then further improve the implementation by optimizing step 2 - say reducing measures of the cells.
Related
I'm looking for an example of how to create a circular buffer using MediaCapture to record seconds before a trigger and after, something similar to Raspberry Pi's
picamera.PiCameraCircularIO(camera, seconds=clip_length).
I am creating a UWP app, which uses a USB camera and excepts a trigger, but I would like to have the Pre and Post timer around the trigger.
You need to implement a queue to store frames in it. Think you have one feame per second then you need queue of frames to store before and after triger specific seconds.
For example you need 15 seconds before and after the trigger.
In your queue you add image of each second to the queue and check when the queue got full (in this case 15 frames) dequeu one item and add new frame to queue. By this way you always have 15 frames before event got triggered. I think the next 15 frames after triggering event is simple enough ;)
I need to animate a MapPolyLine such that on a given event, the start pin zips up to the end pin. The approach I am considerg is to animate frames such that I divide the MapPolyLine into n number of segments and decrease the TimeSpan ts between each frame along the logic of my chosing (to keep things simple, let's just say ts = ts / 2 after each cycle).
I know that one cannot animate the MapPolyLine, but one can change the appearance of the line by updating the latitude and longitude of the end position. My question concerns timing. My experience with multithreading is minimal, so I did not want to take the risk of a user running into a threading based error that may be difficult to diagnose. Should I:
use a simple DispatcherTimer and tick method
use a BackgroundWorker that reports progress every-time the TimeSpan has elapsed
use a dummy animation and attach an event handler to the rendering event
solution other than the above mentioned options?
Thank you in advance for your help!
Decided to use the DispatcherTimer considering the amount of time the animation is going to take - by creating a separate animation object that holds state and its own dispatch timer, it ended up being more efficient than using separate threads because the callback would mean interrupting the main UI thread and based on the requirements it was highly unlikely that there will be more than 2-3 of these animations occuring simultaneously with 95% or greater being only 1 animation at a time.
Again I apologize for a question that might be simple to all of you. I have a limited understanding of what goes behind the scenes in Silverlight.
I have a charting app (Visiblox) that I use as a rolling scope updated every 20ms, adding and removing a point. In pseudocode:
List<Point> datapoints= new List<Point>();
Series series = new Series(datapoints);
void timer_tick(){
datapoints.Add(new Point);
datapoints.RemoveAt(0);
// no need to refresh chart, it does refresh automatically
}
When running 6 series in this charting tool, it started to show a bit sluggish. Changing the tick to 10ms made no difference whatsoever, chart was updated at the same speed, so it seems that 20ms is the speed limit (UI or chart?).
I tried with CompositionTarget.Rendering and got the same results: below 20ms there was no difference in speed.
Then I accidentally enabled both and speed doubled. So I tested with multiple threads (2, 3, 4) and speed doubled, tripled and quadrupled. This has no locks yet, as I don't even know what process I need to generate a lock on, but got no data corruption nor memory leaks.
The question I have is why a sluggish chart at 20ms can not run at 10ms but is ridiculously fast when multithreaded? Is the UI refresh process being run faster? Is the chart computation doubled? Or is there a limit to how fast a single DispatcherTimer can be executed?
Thanks!
Edit: I have a background of embedded coding, so when I think of threads and timings, I immediately think of toggling a pin in hardware and hook up a scope to measure process lengths. I am new to threads in C# and there are no pins to hook up scopes. Is there a way to see thread timings graphically?
A DispatcherTimer, which fires its Tick event on the UI thread, is what's considered a low-resolution or low-accuracy timer because its Interval effectively means "tick no sooner than x since the last tick". If the UI thread is busy doing anything (processing input, refreshing the chart, etc.) then it will delay the timer's events. Furthermore, having a bunch of DispatcherTimer's ticking away on the UI thread at very low intervals will also slow down the responsiveness of your application because while the Tick event is being raised, the application can't respond to input.
So as you noted, in order to process data frequently, you should move to a background thread. But there are caveats. The fact that you aren't currently observing corruption or other bugs could be purely coincidental. If the list is being modified on a background thread at the same time the foreground thread is trying to read from it, you will eventually crash (if you're lucky) or see corrupt data.
In your example, you have a comment that says "no need to refresh chart, it does refresh automatically." This makes me wonder how does the chart know that you have changed the datapoints collection? List<T> does not raise events when it is modified. If you were using an ObservableCollection<T> I would point out that each time you remove/add a point you are potentially refreshing the chart, which could be slowing things down.
But if you are in fact using List<T> then there must be something else (perhaps another timer?) that is refreshing the chart. Maybe the chart control itself has a built-in auto-refresh mechanism?
In any event, the problem is a little bit tricky but not completely new. There are ways that you could maintain a collection on a background thread and bind to it from the UI thread. But the faster your UI refreshes, the more likely you'll be waiting for a background thread to release a lock.
One way to minimize this would be to use a LinkedList<T> instead of List<T>. Adding to the end of a LinkedList is O(1), so is removing an item. A List<T> needs to shift everything down by one when you remove an item from the beginning. By using LinkedList you can lock on it in the background thread(s) and you'll minimize the amount of time that you're holding the lock. On the UI thread you would also need to obtain the same lock and either copy the list out to an array or refresh the chart while the lock is held.
Another possible solution would be to buffer "chunks" of points on the background thread and post a batch of them to the UI thread with Dispatcher.BeginInvoke, where you could then safely update a collection.
The key here I think is to realise that Silverlight renders at a maximum frame rate of 60fps by default (customisable through your MaxFrameRate property). That means that the DispatcherTimer ticks will fire at most 60 times per second. Additionally, all the rendering work happens on the UI thread as well so the DispatcherTimer fires at the rate that the drawing is happening at best, as pointed out by the previous poster.
The result of what you're doing by adding three timers is just to fire the "add data" method 3 times per event loop rather than once, so it will look like your charts are going much faster but in fact the frame rate is roughly the same. You could get the same effect with a single DispatcherTimer and just add 3 times as much data on each Tick. You can verify this by hooking into the CompositionTarget.Rendering event and counting the frame rate there in parallel.
The ObservableCollection point made previously is a good one but in Visiblox there is a bit of magic to try and mitigate the effects of that so if you're adding data at a very fast rate the chart updates will be batched up at the rate of the render loop and unnecessary re-renders will be dropped.
Also regarding your point about being tied to the ObservableCollection implementation of IDataSeries, you are entirely free to implement the IDataSeries interface yourself, for example by backing it with a simple List. Just be aware that obviously if you do that the chart will no longer automatically update when data changes. You can force a chart update by calling Chart.Invalidate() or by changing a manually set axis range.
I need to load 101 bitmaps from the filesystem (they can't be built into the app as a resource as they will be changed for each run of the program) into a windows form application picturebox sequentially based on short duration timer events (500ms give or take) .
Essentially it should work like a slow animation but it is critical that every image be shown.
I've roughed out a simple application in C# to do this however it seems that the image loading and displaying is taking longer than the 500ms so some images are never displayed.
Is there some way I can avoid this? Preloading or creating 101 pictureboxes and showing and hiding?
Anybody have any suggestions?
What's taking the longest? Image loading or displaying? Are you loading each image when it needs displaying? A look at your code would be really valuable.
If you are certain that it will always be exactly 101 images, load them all into an array of System.Drawing.Bitmap first then have an iterator variable that gets incremented on each call of the Tick event of a Timer. Have this Tick event load the image from the array into the PictureBox using PictureBox.Image = myBitmapArray[iterator] If you increment the iterator using ++i%=101; you won't get an OutOfBounds error and the animation will loop.
Populate an array of Bitmap objects before starting the animation.
A couple of options... pick one or combine them:
(1) Use a lock and a counter to guarantee that when the event fires it's loading the next image in line.
(2) Disable the timer in the Tick event, then re-enable it after you've loaded the image. The result is that the images arrive 500ms after the last one is drawn, so if a picture takes one second to load, the images are drawn at t=1000ms, t=1500ms, t=3000ms, etc. All the images are drawn, and 500ms is guaranteed to pass between pictures, but the animation might appear slow.
(3) Do the above, but track the time the event starts, and after the image is drawn, set the next timer tick to be 500 - (Now - eventStart)... so that if the image takes 250ms to draw, the next timer tick will fire in 250ms. If Now - eventStart < 0, the next timer tick should fire immediately. The animation will take the minimum amount of time possible, but images could potentially flash by, appearing only for a few milliseconds.
(4) Use PictureBox.LoadAsync() to give you some multi-threading... the next event can be loading the image while the previous event is drawing. But you'll need a Mutex that you release in the LoadCompleted event that you wait on before calling LoadAsync(), if you need to guarantee the images are all drawn.
(5) I'm not sure if the drawing of the picture falls under the Layout category, but you can try calling SuspendLayout() and ResumeLayout() before/after loading the image
(6) Use an array of images, lock a counter, and use the .Image property of the PictureBox to let you pre-load the images. I believe this was suggested in another answer, also
HTH,
James
I don't have a concrete answer for you, but I would approach this by first determining if it's image loading, image display, or both actions that are taking too much time.
I would imagine that image loading is going to be relatively quick, even with pretty large image sizes, provided that the images are local and you have relatively decent hardware. My first attempt would involve loading all images from a thread sequentially so that you application doesn't have to wait for image display to complete before the next image loads.
If image display is taking a long time (and even on my really powerful workstation it's not all that fast for large images), then is it possible for you to scale the images before the application displays everything? Does your application need to deal with full resolution images? With the megapixel cameras these days, I can't image that you'd want to have all of the data present in the image files anyway, since the sizes can easily exceed monitor resolutions by a factor of 6.
Another thing that may be a concern is the size of the images. If the are all 18 Megapixel Images, I can see it taking either a lot of time or a lot of room.
You may want to resize them to the size of your display area when you initially load them up so that you aren't using 2 gigs of ram or waiting to read off the disk depending on how you implement it.
I'm currently working on an app that allows the user to play (automatically scroll) through a series of local images. Usually there will be five or six on screen at once.
The major bottleneck at the moment seems to be the actual loading of the image data from disk. A timer thread calls for the images to be updated every 1/6 of a second and the app is struggling to keep up with that speed. Each image is around 25Kb.
I tried creating a rolling cache to try and preload images but this was also getting caught up with itself so ended up slowing down just as much.
Every beat of the timer, I'm looping through the six image placeholders loading the next image using the standard
Image img = Image.FromFile("filename");
method but thought someone might know of a faster way to get the images off disk.
There are between 500 and 20,000 images in each of the six sets so it's too large to load the whole thing into memory at the start.
If anyone has suggestions for a faster way to pull these images through, it would be greatly appreciated.
Edit to add some more detail of application flow.
Okay, this is what's happening:
User hits 'play' button. Timer thread starts with 1/6 second timeout.
Timer callback:
Update image index (_index++)
for each viewer in list of visible viewers (the forms to display images)
{
get the filename from the id stored in the viewer
check to see if the file exists
if it does exist,
create new bitmap from image
and return that image
otherwise return null
if returned image isn't null, display it on screen
}
That's obviously going across a few layers - the image loading goes on in the services layer and then passes this through to presentation and then to the UI but that's the gist of what's happening.
I came across this page which describes how to use the GDI+ API directly to load images. Very simple to use:
ImageFast.FromFile(#"C:\MyPhoto.JPG");
Added to show speed of ImageFast over Image From File method
This uses the source code found here. The code was copied and pasted and required no changes.
Stopwatch watch = Stopwatch.StartNew();
string filePath = #"C:\TestImage25k.png";
Image fromFile = Image.FromFile(filePath);
watch.Stop();
Console.WriteLine("Image.FromFile Ticks = {0:n}", watch.ElapsedTicks);
long fromFileTicks = watch.ElapsedTicks;
watch.Reset();
watch.Start();
Image fastImage = ImageFast.FromFile(filePath);
watch.Stop();
long fastFileTicks = watch.ElapsedTicks;
Console.WriteLine("ImageFast.FromFile Ticks = {0:n}", watch.ElapsedTicks);
Console.WriteLine("fromFileTicks - fastFileTicks = {0:n}", fromFileTicks - fastFileTicks);
The console output was
Image.FromFile Ticks = 19,281,605.00
ImageFast.FromFile Ticks = 7,557,403.00
fromFileTicks - fastFileTicks = 11,724,202.00
You can see the impact of the ImageFast. Over time those 11 million saved ticks will add up.
Easiest might be to put a 'next' and 'previous' button to limit the number of images and preload.
Check out the concept of double buffering. What you want to be doing is have a second thread that can be loading the next set of images while you are displaying the first set. Once the 1/6 time gate hits, you switch the one set of images out and start loading the next set.
I think concept of double buffering will be useful. Set "Double Buffer" property of the form to True. This will help you little bit. Following links may be useful to you
http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/f15ae586-b63f-4afb-90a7-d9067ccc19d5
How to speed up .NET winforms rendering
If you have 6 images displayed at once, and you change them all every 1/6 of a second, you should be running into performance issues. Loading 150 kb from disk should be a trivial activity even without caching. It sounds like you may be overdoing the file loads. Are you sure you are only loading 6 images at a time? Are you reading images from disk that are not displayed?
If you can you provide a little more detail of the application flow, I may be able to be a little more helpful.
i would probably create a background thread to continously fetch all the images from disk (keeps the ui responsive) and then publish each newly loaded image via an event