I am trying to draw graphics on a form application based on data from an externally connected USB device to my PC. my goal is to continuously uploading the data from USB device and updating the graphics like every 20ms.
First, I made the below two codes and put them in button_click function. Each time the button is clicked, they work fine.
uploadData(); // this uploads 2KB data from USB device connected to my PC
drawGraphics(); // this draws graphics on a picture box
So as next step, I put them in while infinite loop like below. But drawing does not work while data uploading from the USB device keeps running. I was probing the USB device hardware and I confirmed it keeps sending new data to my PC.
while(true)
{
uploadData();
drawGraphics();
}
I put Thread.Sleep() between the above codes and put various delay values to see if the problem is solved, but no success.
Interesting thing is that each time when I move mouse's cursor over the form, the drawing starts a bit but stops at early point.
This could be related to very simple mistake. I am kind of new to Visual C# so just hit this wall and not able to overcome it.
Usually the way to handle an occasional-update requirement in a GUI app is to use a timer. The timer runs on a background thread and notifies the main thread occasionally that a "tick" has occurred. This way, other operations like processing mouse and keyboard input, drawing to the screen, etc. can continue. I'm not entirely sure why your solution isn't working, but I'm 99% sure you can fix it by replacing the while loop with a System.Windows.Forms.Timer that ticks on the desired interval.
So, I recommend: adding a Windows Forms Timer to your form via the Visual Studio designer, setting its Interval property to the desired number of milliseconds, registering an event handler for the timer tick, moving the uploadData() call to that event handler, and moving the content of the drawGraphics() method to the PictureBox's Paint event.
Instead of having an infinite loop, create a timer control. Set the Interval to 20 (thats 20 ms). In the OnTick create an Method that:
1) Send the Enabled property of your timer to 'False'
2) Calls your upLoadData and drawGraphics methods
3) Sets the Enabled property of your timer to 'True'
This way you won't simultaneously try to access the data on the USB more than once at a time if for some reason the 1st occurence takes a little longer than expected.
Related
A bit of context first
I have a Xamarin app that essentially streams video from a remote server. I have a background thread that loops like this (pseudo-code):
private void UpdateMethod()
{
while (running)
{
bool success = WaitForUpdate();
if (!success)
{
break;
}
Update update = GetUpdate();
SendUpdateToConcurentQueue(update);
}
Disconnect();
}
I start the background thread like this:
Thread thread = new Thread(UpdateMethod);
thread.IsBackground = true;
thread.Start();
The issue
When I start the stream, everything is perfect. It's only after ~10 seconds of not interacting with the device that it becomes really slow. I've outputted the number of updates from the background thread, and they seem to come in a lot slower. I usually get around 2-6 updates to process per update (60fps). When it's super slow, I get 1 ever 6 update cycle.
One thing that puzzles me: When I pull down the iOS top bar menu, the updates go back up and the stream is suddenly back to normal speed. Update rate goes up for ~10 seconds and it goes back to lagging like crazy.
What I've tried
I tried to start a Dispatch queue with only this in it, like this:
DispatchQueue queue = new DispatchQueue("updateQueue");
queue.DispatchAsync(this.UpdateProcess);
It didn't seem to help at all.
I also tried to change the QualityOfService property in my update thread like this:
NSThread.Current.QualityOfService = NSQualityOfService.UserInitiated
Doesn't work either! It seems to me that iOS lowers my thread's priority for some reason. If I put a breakpoint in my UpdateMethod method, it's being hit when the app doesn't lag. But when there's lag, the breakpoint doesn't get hit. Now this really puzzles me, since the code still runs! I still receive the updates, it's just way slower...
Edit: I tested using Instruments and found that the network is being throttled... Investigating, but if anyone has knowledge of any kind of network throttle on iOS, let me know.
Try setting the IdleTimerDisabled to true, we do this all the time in iOS games to keep iOS from idling our games.
Note: We do this in a polite way only when the user is not touching the screen due to watching a replay, level changing multimedia segues, etc...
Note: Make sure that you do reset the idle when you do not need it (when you app does go in the background, etc...), as from killing battery and making users bummed out about your app to the real killer: Apple Store rejections
Apple: App Idle Timer info
Xamarin: UIKit.UIApplication.IdleTimerDisabled Property
The default value of this property is NO. When most apps have no touches as user input for a short period, the system puts the device into a "sleep” state where the screen dims. This is done for the purposes of conserving power. However, apps that don't have user input except for the accelerometer—games, for instance—can, by setting this property to YES, disable the “idle timer” to avert system sleep.
| IMPORTANT
You should set this property only if necessary and should be sure to reset it to NO when the need no longer exists. Most apps should let the system turn off the screen when the idle timer elapses. This includes audio apps. With appropriate use of Audio Session Services, playback and recording proceed uninterrupted when the screen turns off. The only apps that should disable the idle timer are mapping apps, games, or programs where the app needs to continue displaying content when user interaction is minimal.
I have to use a camera SDK for a microscope that comes with a sample C# Windows Forms application.
The SDK functions are imported to the app via DLLImport.
In this sample application the single frames from the camera are read from RAM via a callback function.
This callback function then updates a PictureBox to show the live image.
For my useage however I want to not only show the frames, but also record them.
I think the easiest way to do this is by using SharpAvi.
However I don't know how to initialize the AviWriter (I obviously can't initialize it everytime the callback fires) and then add the single frames to the stream from the callback function.
At the moment I solved my problem by using another function that waits in a seperate thread for a public counter to go up - the counter itself is updated in the callback function.
Everytime the counter is updated this function then also reads the frame from RAM and adds it to the AviWriterStream.
To top it of I had to make the thread block my UI by using
var resetEvent = new ManualResetEvent(false);
System.Threading.ThreadPool.QueueUserWorkItem(delegate
{
WriteAVI()
resetEvent.Set();
}, null);
resetEvent.WaitOne();
This is due to the fact that I need to record several videos at different XY positions - so everytime my for loop arrives at a new XY position the recording is triggered and I have to make sure to only move to the next position once the recording is actually finished.
My way of doing this is obviously hackish and very bad practice (I already feel bad but just don't know better) and I am wondering what the correct solution would be.
So far it works - just the UI freeze is really annoying.
Edit: These are probably two questions:
1) How to correctly write frames to the AVI and
2) How to wait for the recording to be completed without making it freeze my UI
Is there any way to catch whole screen re-paint event? (windows, c#)
I want to do CopyFromScreen only after screen was updated, not by timer.
There is no such thing as a whole screen paint. The system optimises and only updates invalid regions. I don't know what you are trying to achieve (you didn't say) but it sounds like a remote desktop type application. They typically use mirror drivers.
There is no such thing as a whole screen paint
that is true, but the screen can't update faster than its refresh rate (60-80 fraps per second). You need to set a timer with that interval and to make screenshots in its Tick event.
I have a strange issue that I'm not too sure on how to fix or address. I'm writing a mini text editor style application - RichTextBox editor.
I need to do some complex parsing after the selection changes - updating position, selection text and various other bits about the context of the text around the area.
As it takes a bit of processing I don't want it to fire each time the selection changes if the user is scrolling with their arrow keys. I thought of using the Application.Idle, but it fires too regularly. I tried a timer, but it may fire while the selection arrows are still moving.
What I was thinking of was a countdown timer sort of utility that will reset the timer each time the RichTextBox SelectionChanged event fires, then when the timer hits 500 ms or 1000 ms it will execute the complex processing runs.
Does this sound like a good idea?
You should probably start your processing in its own thread when it takes too long. As soon as you get new inputs you can stop the previous calculation and start with the new information again (so consider a cancel mechanism for your thread).
When your thread is done you have to check if its results are valid (the selecion did not change in the meantime). Finally, you can "synchronize" the results of the calculation to the GUI, which is hopefully quick enough :)
This does only work, when there is a certain amount of calculation that can be done without writing to the GUI ... I am not sure if you can implement it this way. It depends on the type of your calculations.
I am using C# .NET to take a screenshot of the contents of a second monitor and display it in a windows on the primary screen.
The code I have is:
screenShotGraphics.CopyFromScreen(
Screen.AllScreens[screen].Bounds.X,
Screen.AllScreens[screen].Bounds.Y,
0,
0,
Screen.AllScreens[screen].Bounds.Size,
CopyPixelOperation.SourceCopy);
This works quite well when it is triggered by a button click, because the slight delay is not noticeable, however when it is run automatically (say every few seconds) the user can easily notice their mouse 'lock up' for a few seconds.
Obviously that's not ideal. So is there a faster way to perform this operation? (Or a way to perform it without interrupting mouse movements or interactivity?
You could try performing the screen shot with a BackgroundWorker Control, which is an easy way of running the function on a separate thread. Just call your screen shot function within the DoWork event of the BackgroundWorker and whenever you want to run your function just call:
yourBackgroundWorker.RunWorkerAsync()
Edit:
It's probably doing this so anything moving on the screen (like the mouse) won't blur the screenshot. You could try to break the screen down into smaller sections and take screenshots, then stitch them together. This would free the mouse for movements between each partial screenshot since you're on a separate thread, but it runs the risk of something changing on the screen (depending on how long it actually takes)
Try to make the call on the principal thread and if you need to save the image to file, do it in another thread...
I think that there isn't other way, cuz the CopyFromScreen, calls the BitBlt api function, witch is the one you must call if you want to do this by api calls... So that is the only thing that Windows provides.