I want to run an unknown amount (unknown at compile time) of NSTasks and I want to run an unknown amount (again, at compile time, max. 8) of them simultaneously. So basically I loop through a list of files, generate an NSTask, run it until the maximum of simultaneous tasks are ran and whenever one finishes another NSTask starts until all of them are done.
My approach would be creating a class that generates an NSTask and subclass it to change parameters here and there when there's a different input (changes that are made from the interface). Then the superclass will run the NSTask and will have an #synthesize method returning its progress. Those objects will be generated in the above repeat loop and the progress will be displayed.
Is this a good way to go? If so, can someone give me a quick example of how the repeat loop would look like? I don't know how I would reference to all objects once they're run.
for (; !done ;) {
if (maxValue ≥ currentValue) {
//Run Object with next file.
//Set currentValue.
}
//display progress and set done to YES if needed and set currentValue to it -1 if needed
}
Thanks in advance.
There's no loop exactly.
Create an array for tasks not yet started, another with tasks that are running, and another with tasks that have finished. Have a method that pulls one task from the pending-tasks array, starts (launches) it, and adds it to the running-tasks array. After creating the arrays and filling out the pending-tasks array, call that method eight times.
When a task finishes, remove the task from the running-tasks array and add it to the finished-tasks array, then check whether there are any tasks yet to run. If there's at least one, call the run-another-one method again. Otherwise, check whether there are any still running: If not, all tasks have finished, and you can assemble the results now (if you haven't been displaying them live).
Related
I have written a go program which is doing many tasks concurrently (in goroutines), and showing the status of these task on the console like this -
[Ongoing] Task1
[Ongoing] Task2
[Ongoing] Task3
Now Any of these tasks can finish first or last. I want to update the status of these tasks at the same place. If Task2 finishes first then it should show something like this-
[Ongoing] Task1
[Done] Task2
[Ongoing] Task3
I tried uilive library, but It's always updating the last line like this. (I think it's not for updating multiple lines)
[Ongoing] Task1
[Ongoing] Task2
[Done] Task2
How do I achieve this?
I was looking to implement a similar functionality and came across this question. Not sure if you're still looking for a solution, but I found one :)
It turns out uilive can very well be used to update multiple lines, by making use of the Newline() function on a *uilive.Writer. Editing the example on their repository to write the download progress on multiple lines, we get:
writer := uilive.New() // writer for the first line
writer2 := writer.Newline() // writer for the second line
// start listening for updates and render
writer.Start()
for i := 0; i <= 100; i++ {
fmt.Fprintf(writer, "Downloading File 1.. %d %%\n", i)
fmt.Fprintf(writer2, "Downloading File 2.. %d %%\n", i)
time.Sleep(time.Millisecond * 5)
}
fmt.Fprintln(writer, "Finished downloading both files :)")
writer.Stop() // flush and stop rendering
For implementing something to track the progress of multiple concurrently running tasks, as #blami's answer also states, a good approach is to have a separate goroutine that handles all terminal output.
If you're interested, I've implemented this exact functionality in mllint, my tool for linting machine learning projects. It runs all its underlying linters (i.e. tasks) in parallel and prints their progress (running / done) in the manner that you describe in your question. See this file for the implementation of that. Specifically, the printTasks function reads from the list of tasks in the system and prints each task's display name and status on a new line.
Note that especially with multi-line printing, it becomes important to have control over flushing the print buffer, as you do not want your writer to automatically flush halfway through writing an update to the buffer. Therefore, I set the writer's RefreshDuration to something large (e.g. time.Hour) and call Flush() on the writer after printing all lines, i.e. at the end of printTasks.
Stdout is a stream so you can't address already printed line or character and change it later. Such updates in CLI libraries are made by moving cursor back (by printing escape sequences - non printable character sequences that affect users terminal) and overwriting the text. For that a reference point is needed so the library (or you) know where cursor is and how many lines were printed, etc.
One of possible approaches can be creating a separate goroutine that handles all terminal output printing and have other goroutines that do the actual work only communicate updates (e.g. over channels) to it. Centralizing "state" of terminal in such routine should make it easier to update using technique describe above.
While not a drop-in solution for your situation I recommend to look at mpb - a library that allows to render multiple asynchronously updating progress bars. Maybe you can design your solution in similar way or use it as base as it already handles differences between OS'es, etc.
I have pre-configuration file(with many parameters), the value of which I keep in CoreData.
Let's call it the first task:
Create new instance of NSManagedObjectContext: NSManagedObjectContextVariable.
[parametersInFileArray enumerateObjectsWithOptions:NSEnumerationConcurrent
usingBlock:^(id obj, NSUInteger idx, BOOL *stop){
[NSManagedObjectContextVariable performBlock:^{
bla-bla-bla
insertNewObjectForEntityForName:entityName1 inManagedObjectContext:NSManagedObjectContextVariable;
[NSManagedObjectContextVariable save:&error];
}
}
Then I want to process each value(stored earlier in CoreData) concurrency and save it to CoreData(entityName2 with relationship One-to-Any with entityName1). Let's call it the second task:
1.Create new instance of NSManagedObjectContext.
2.Get (NSArray *)fetchedObjects form entity("entityName1")
3.
[fetchedObjects enumerateObjectsUsingBlock:^(entityName1Class *obj, NSUInteger idx, BOOL *stop){
NSArray* newParameters = getManyNewParametersForObj(obj);
[newParameters enumerateObjectsUsingBlock:^(Parameter *param, NSUInteger idx, BOOL *stop)
{
bla-bla-bla
insertNewObjectForEntityForName:entityName2 inManagedObjectContext:NSManagedObjectContextVariable;
[NSManagedObjectContextVariable save:&error];
}
}
So. I need execute Task 1 and Task 2 consecutively after each other. And separate from the main thread. The second task can not start until the first task is not finished.
In Task 2 I need to start getManyNewParametersForObj+insertNewObjectForEntityForName+save for each element from fetchedObjects(Obj) concurrency. Is a long operations(get Parameters from Net) and they do not depend on each other.
On every save in Task 1 and Task 2, I update NSTableView(Observe NSManagedObjectContextDidSaveNotification).
I am very confused by dispatch_apply, performBlock, enumerateObjectsUsingBlock, enumerateObjectsUsingBlock, enumerateObjectsWithOptions:NSEnumerationConcurrent, semaphoreWait, semaphoreBlock, blockUntilWait, serialQueue, parallelQueue etc.
Advise me how to do what I need.
Thanks.
Did you look at MagicalRecord and SMC?
MagicalRecord can help with the creating of contexts, saving in a block (other thread) and the merging back into the parent context.
So to setup a context and thread becomes;
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext)
The block will be execute on its own thread using its own context. Further you can define a completion block that will perform on the main thread. This way you have feedback between your background thread and the main thread. And you avoid going into semaphores.
SMC is a Finite State Machine compiler for Objective C and other languages. It might take a little time to understand their syntax and their way of implementing a FSM, but it is definitely worth the upfront effort. Once implemented maintenance and changes will become really easy. Eitan Suez has produced a great tutorial PDF.
With SMC define a state for each of your tasks. Each state will have an entry action. The entry action will be the method containing the code that you show in your question.
At the end of State 1 or lets call it Task 1, you fire the transition to the next state. The FSM will switch over and will perform the entry action of the next defined state, lets say Task 2. This way Task 1 performs before Task 2.
FSM does not support parallel sub tasks out of the box. If you want to run the subtasks of super task 2 in parallel, then you would need to monitor completion of each sub task. I do this with three counters.
totalTasks it the overall number of subtasks started
goodTasks increments when a subtasks has finished without error
failedTasks increments when a subtask has encountered a problem.
Now, when goodTasks + failedTasks == totalTasks then all subtasks of supertask 2 have finished. If failedTasks == 0 then all went well.
A failedTask can make the FSM to switch to an error handling state, for example.
There are other Finite State Machine implementations around but I found SMC to be really flexible.
I want to start two Async Tasks but the second will not start until the first has completed.
From what I've googled, people usually suggest this approach:
new MyAsyncTask().execute(params);
new MyAsyncTask().execute(params);
However, I need to instantiate them separately and also keep the handles of the task's (to pass messages for example). Therefore, I SORT OF do this:
onStart()
{
taskA = new MyAsyncTask(paramsA);
taskB = new MyAsyncTask(paramsB);
}
onButtonPress()
{
taskA.execute();
taskB.execute();
}
Edit:
I've noticed that taskB does not actually start executing until taskA completes (which runs a tcp/ip server so it takes a long time). I cannot figure out why. Any thoughts or comments ?
The short answer is that, depending on your version of Android, all AsyncTask subclasses may be using the same thread, so you can only do one at a time. There are two ways around this:
Use Runnable instead of AsyncTask
Replace one call to execute with executeOnExecutor(Executor.THREAD_POOL_EXECUTOR, params)
Clearly, try #2 first - it's less of a code change. But if that doesn't work pretty quickly, I'd switch to #1. In that case, you don't have to worry about how Android might change in the future.
If you want more details about the threading model for AsyncTask, have a look at the Android doc entry.
I need to perform data analysis on files in a directory as they come in.
I'd like to know, if it is better,
to implement an event listener on the directory, and start the analysis process when activated. Then having the program go into sleep forever: while(true), sleep(1e10), end
or to have a loop polling for changes and reacting.
I personally prefer the listeners way, as one is able to start the analysis twice on two new files coming in NEARLY the same time but resulting in two events. While the other solution might just handle the first one and after that finds the second new data.
Additional idea for option 1: Hiding the matlab GUI by calling frames=java.awt.Frame.getFrames and setting frames(index).setVisible(0) on the index matching the com.mathworks.mde.desk.MLMainFrame-frame. (This idea is taken from Yair Altman)
Are there other ways to realize such things?
In this case, (if you are using Windows), the best way is to use the power of .NET.
fileObj = System.IO.FileSystemWatcher('c:\work\temp');
fileObj.Filter = '*.txt';
fileObj.EnableRaisingEvents = true;
addlistener(fileObj,'Changed',#eventhandlerChanged);
There are different event types, you can use the same callback for them, or different ones:
addlistener(fileObj, 'Changed', #eventhandlerChanged );
addlistener(fileObj, 'Deleted', #eventhandlerChanged );
addlistener(fileObj, 'Created', #eventhandlerChanged );
addlistener(fileObj, 'Renamed', #eventhandlerChanged );
Where eventhandlerChanged is your callback function.
function eventhandlerChanged(source,arg)
disp('TXT file changed')
end
There is no need to use sleep or polling. If your program is UI based, then there is nothing else to do, when the user closes the figure, the program has ended. The event callbacks are executed exactly like button clicks. If your program is script-like, you can use an infinite loop.
More info in here: http://www.mathworks.com/help/matlab/matlab_external/working-with-net-events-in-matlab.html
I have a GUI app that has a main thread and then I use NSOperation to run 2 other threads once the user clicks the Start button. Now one thread calculates a certain value and updates it. What I want thread 2 to do is to pick this value up and update the UI.
How do I get a IBOutlet Textfield value to get updated on the UI from this second thread ?
eg:
main.m --- handles the UI and has code to start the 2 threads when the user hits the Start Button.
thread1.m -- calculates a particular value and keeps doing it until the user hits stop.
thread2.m - Need to use this thread to update the UI in main.m with the the value that thread1.m calculates.
I am unable to accomplish the thread2.m task and update the UI. My issue is that how do I define a IBOutlet and update it with a value from thread2/1 so that the main.m has access to this value and updates the UI. I have access to the actual variable in main.m and can print it out using NSLog. Its just that I am getting stuck on how to update the UI with this value. As I need to have theIBOutlet in main.m to tie it with the UILabel in the app. Any ideas guys ? Thanks.
Could you add pointers to your thread1.m and thread2.m files? Then set them with either a constructor method or some accessor methods?
If I understand the situation you described in your example, and assuming what you are calculating is an int (you can modify as you need):
Add an accessor to thread1.m
-(int)showCurrentCalcValue
{
//Assume that you get calculatedValue from whereever else in your thread.
return calculatedValue;
}
Then add to thread2.m
NSTextField *guiTextField;
Thread1 *thread1;
-(void) setThread: (Thread1 *aThread)
{
self.thread1 = aThread;
}
-(void) setGuiTextField: (NSTextField *aTextField)
{
self.guiTextField = aTextField;
}
-(void) updateGUI()
{
[guiTextField setStringValue: [thread1 showCurrentCalcValue]];
}
Presuming your main.m is something like the following:
IBOutlet NSTextField *outputDisplay
-(void) setUpThreads()
{
Thread1 *thread1 = [[Thread1 alloc] init];
Thread2 *thread2 = [[Thread2 alloc] init];
[thread2 setGuiTextField: outputDisplay];
[thread2 setThread: thread1];
//Whatever else you need to do
}
Then just take care of setting everything and calling the methods in your threads.
Source code files don't matter. You could have all of this stuff in one file (not that that would be a good idea) and the problem would be unchanged. What matters are the classes.
Classes are not simply bags of code; you design them, you name them, and you define each class's area of responsibility. A class and/or instances of it do certain things; you define what those things are and aren't.
When writing NSOperation subclasses, don't worry about the threads. There's no guarantee they even will run on separate threads. Each operation is simply a unit of work; you write an operation to do one thing, whatever that may be.
eg: main.m --- handles the UI and has code to start the 2 threads —
operations
— when the user hits the Start Button.
thread1.m -- calculates a particular value and keeps doing it until the user hits stop.
That's not one thing; that's an indefinite sequence of things.
thread2.m - Need to use this thread to update the UI in main.m with the the value that thread1.m calculates.
You should not touch the UI from (what may be) a secondary thread. See the Threading Programming Guide, especially the Thread Safety Summary.
I don't see why this should even be threaded at all. You can do all of this much more easily with an NSTimer running on the main thread.
If it would be inappropriate to “calculate… a particular value” on the main thread, you could make that an operation. Your response to the timer message will create an operation and add it to your computation queue. When the user hits stop, that action will go through on the main thread; invalidate the timer and wait for the queue to finish all of its remaining operations.
With either solution, “thread2.m” goes away entirely. Your update(s) to the UI will (and must) happen entirely on the main thread. With the latter solution, you don't even have to wait until you're done; you can update the UI with current progress information every time you receive the timer message.