A for loop let my CPU run on 100 %. The problem is I want to change some things on the view. For example I want to use a progressView, but everything on the view only changes when the loop is finished.
Is it possible to solve my problem?
And as always, sry for my bad english.
You need to use some form of concurrency to achieve this, so that your iteration and UI updating tasks can occur in parallel with each other. Apple's Concurrency Programming Guide provides an introduction to the various forms of concurrency available.
Move your for loop onto an asynchronous GCD queue, being sure to put any UIKit messages on the main queue. This will free up the UI thread for any view changes that you want to occur.
Related
I have a program I'm writing in vb.net that has ballooned into the most complicated thing I've ever written. Because of some complex math and image rendering that's happening constantly I've been delving into multithreading for the first time to improve overall performance. Things have honestly been running really smoothly, but we've just added more functionality that's causing me some trouble.
The new functionality comes from a pair of DLLs that are each processing a video stream from a USB camera and looking for moving objects. When I start my program I initiate the DLLs and they start viewing the cameras and processing the videos. I then periodically ping them to see if they have detected anything. This is how I start and stop them:
Declare Function StartLeftCameraDetection Lib "DetectorLibLeft.dll" Alias "StartCameraDetection" () As Integer
Declare Function StopLeftCameraDetection Lib "DetectorLibLeft.dll" Alias "StopCameraDetection" () As Integer
When I need to check if they've found any objects I use several functions like this:
Declare Function LeftDetectedObjectLeft Lib "DetectorLibLeft.dll" Alias "DetectedObjectLeft" () As Integer
All of that works really well. The problem is, I've started to notice some significant lag in my UI and I'm thinking it may be coming from the DLLs. Forgive my ignorance on this, but as I said I'm new to using multiple threads (and incorporating DLLs too if I'm honest). It seems to me that when I start a DLL it running it's background tasks on my main thread and just waiting for me to ping it for information. Is that the case? If so, is it possible to have the DLL running on a sperate thread so it doesn't affect my UI?
I've tried a few different things but I can't seem to address the lag. I moved the code that pings the DLL and processes whatever information it gets into a sperate thread, but that hasn't made any difference. I also tried calling StartLeftCameraDetection from a separate thread but that didn't seem to help either. Again, I'm guessing that's because the real culprit is the DLL itself running these constant background tasks on my main thread no what thread I actually call it's functions from.
Thanks in advance for any help you might be able to offer!
There's a lot to grok when it comes to threading, but I'll try to write a concise summary that hits the high points with enough details to cover what you need to know.
Multi-threaded synchronization is hard, so you should try to avoid it as much as possible. That doesn't mean avoiding multi-threading at all, it just means avoiding doing much more than sending a self-contained task off to a thread to run to completion and getting the results back when it's done.
Recognizing that multi-threaded synchronization is hard, it's even worse when it involves UI elements. So in .NET, the design is that any access to UI elements will only occur through one thread, typically referred to as the UI thread. If you are not explicitly writing multi-threaded code, then all of your code runs on the UI thread. And, while your code is running, the UI is blocked.
This also extends to external routines that you run through Declare Function. It's not really accurate to say that they are doing anything with "background tasks on the main thread", if they are doing anything with "background tasks" they are almost certainly implementing their own threading. More likely, they aren't doing any task breakdown at all, and all of their work is being done on whichever thread you use to call them---the UI thread if you're not doing anything else.
If the work being done in these routines is CPU-bound, then it would definitely make sense to push it off onto a worker thread. Based on your comments on what you already tried:
I moved the code that pings the DLL and processes whatever information it gets into a sperate thread, but that hasn't made any difference. I also tried calling StartLeftCameraDetection from a separate thread but that didn't seem to help either.
I think the most likely problem is that you're blocking in the UI thread waiting for a result from the background thread.
The best way to avoid this depends on exactly what the routines are doing and how they produce results. If they do some sort of extended process and return everything in function results, then I would suggest that using Await would work well. This will basically return control to the UI until the operation finishes, then resume whatever the rest of the calling routine was going to do.
Note that if you do this, the user will have full interaction with the UI, and you should react accordingly. You might need to disable some (or all) operations until it's done.
There are a lot of resources on Async and Await. I'd particularly recommend reading Stephen Cleary's blog articles to get a better understanding of how they work and potential pitfalls that you might encounter.
In my app, I want to create a class that receives a certain type of notifications, begins it's work and sends out notifications when it's done. I think that later I may need to use concurrency to optimize the app — so this work that the class does is done in separate threads — but right now I don't have any knowledge or experience of working with concurrency and I don't want to spend time on premature optimizaion. However, if I understand correctly, the default usage of notifications doesn't mix with concurrency so well.
Is there a way that I can just follow few simple rules with notifications right now without diving into concurrency, and avoid rewriting all that code later?
Yes, you can avoid a rewrite.
I would write your work/background tasks inside blocks and use GCD (Grand Central Dispatch). This works fine and is easy to use in the non-parallel case, but will also allow you to easily parallelize your work later.
I'd look into NSBlockOperation and NSOperationQueue and/or dispatch_async()
I want to be able to slow down each step in my code, it can be handy for some functions like sending keystrokes. I could add "sleep" after each step but is there a better way?
Sleep is seldom a good way to do things. The right way would be to use a timer. Using a timer won't lock up the thread and keep it from processing other events.
Put the keystrokes that you want to send into a list. Then create a timer object that sends the next keystroke available on each tick.
There are several different timer classes available. Which one to use depends on what kind of application you are creating - console, WinForms, WPF?
As long as you...
only use Thread.Sleep from a non-UI thread
and do not get in the habit of doing it on every single thread you create
and can afford to temporarily "suspend" the calling thread
and it is not currently causing any issues
...then I see no practical reason to deviate from what you are doing now. The reason being that other options require code that is more slightly more complex and difficult to read and would not provide any noticeable improvement in performance or resource allocation if all you are doing is sending keystrokes in a delayed fashion. This would certainly be one problem where KISS reigns supreme. Do not try to solve a problem that does not exist yet.
Add sleep in your code. Its the practice of the most professionals where slowing down the code is needed. Using Sleep, its in ur hand that how much time you want the compiler to take to execute the next line of code.
I would suggest Sleep function.
The reference says this:
"You should call this function from the main thread of your application only."
But I would like to get the current graphics context from separate threads. What do you think? What can I do to reach this?
Edit:
Thanks guys for the answers. I don't know which is good for me at the moment, but thank you very much.
Never draw to the screen from anything other than the main thread!!! The graphics chip is single threaded, so you could cause all kinds of race conditions if you don't follow that rule.
You can draw to a background NSImage and then notify the main thread when you're finished and to update the screen.
If you want to draw from other threads, either create your own CGBitmapContext or use a CATiledLayer.
I would say restructure your logic to conform to the reference's advice.
Generally it is accurate about things you should and shouldn't do.
Why do you want to access it from different threads?
I have a legacy WinForms Mdi App in VB.Net 2.0 which I am adding functionality to. One of the additions is a warning which needs to be raised when the current time nears a specified value (a deadline). My intention is to check the time once an hour until there is less than an hour until the deadline, then display warnings at specified intervals until the time's up.
The user needs to be able to continue to use the app up to and even after the deadline, but they need to periodically be made aware of the deadline's proximity.
The app does not use System.Threading yet and my knowledge of it is limited at this time. I do know that there are 3 different Timer() methods available:
System.Threading.Timer(),
Windows.Forms.Timer() and
System.Timers.Timer()
My question is, which is the best way to go with this? I attempted to use the threaded timer, but since WinForms are not thread safe I got a run time error trying to access another class. Is it worth making the class/form thread safe? Am I completely off track?
Thanks.
This article explains pretty well:
Comparing the Timer Classes in the .NET Framework Class Library
It sounds like System.Windows.Forms.Timer is the one for you.
My guideline: If you want the timer to run on your main GUI thread, stick with Windows.Forms.Timer. If it's okay for your timer to be called asynchronously on a thread pool thread, or if you don't want to experience the small delays that System.Windows.Forms.Timer tends to suffer, use System.Timers.Timer. System.Threading.Timer has a different interface from the other two and is not thread-safe; personally, I'm not a fan.
I would just use the Forms timer. I think I read that it's not as accurate, but it sounds like you don't need it to be.
I agree that Windows.Forms.Timer() is the best for this case as it handles the cross thread marshalling issues.
Some useful related links:
Windows Presentation Foundation Threading Model
WinForms UI Thread Invokes: An In-Depth Review of Invoke/BeginInvoke/InvokeRequred
The System.Forms.Timer actually works on the main thread using the windows message queue. This makes it somewhat inacurate but since you don't really need ms precision it's good enough.
You could use one of the other timers that work on a separate thread but since you need to activate a winforms component that work in the main you'll need to use Form.Invoke or some other way to pass the event to the main thread - which would cause some latency as well.
In conclusion use the System.Forms.Timer when you need to activate a winforms based component.
Ok, first things first...
If you want to show the user a form and do something in the background I would use the BackgroundWorker class, it worked for me before.
Also, you need invoke methods as mentioned before and as Chris said, it sounds harder than what it actually is.
Here's a link which I think will help you out.
http://msdn.microsoft.com/en-us/library/ms171728(VS.80).aspx