How to delete the dispatched block using GCD - macos

I have this code:
_myQueue = dispatch_queue_create("com.myapp", DISPATCH_QUEUE_SERIAL);
_mainQueue = dispatch_get_main_queue();
and lot of this block that require some seconds (or minutes)
dispatch_async(_myQueue,
^{
if(canRun){
dispatch_async(_mainQueue,^{/* updating interface here */});
// code here
}
});
My app have a "Stop" button to try stopping all job, and the BOOL "canRun" help me to execute all blocks w/o do nothing.....but always I have to wait the completition of each block until the queue come 0.
Is there any way to instantly "clean" the queue istead doing that?
The aim is to stop processes and to start over without closing and reopening the application.
This project works under ARC.

You can cancel them if you take a few extra steps to creat a dispatch_source object and keep a reference to it.
Review this for starters
https://developer.apple.com/library/mac/documentation/Performance/Reference/GCD_libdispatch_Ref/index.html
There are functions to pause, resume and cancel.

Related

XMaskEvent not returning

I am following this tutorial here: http://www.sbin.org/doc/Xlib/chapt_16.html
Here is the image of the tutorial:
Here is my code: (it is in another thread from which I called XInitThreads - I know using threads and X is bad, I know I should be on the main thread, but just wondering if possible)
var ev = XEvent();
var rez_XMaskEvent = XMaskEvent(cachedXOpenDisplay(), ButtonPressMask | ButtonReleaseMask, ev.address());
console.log('rez_XMaskEvent:', rez_XMaskEvent);
console.log('ev:', ev);
ButtonPressMask is 4
ButtonReleaseMask is 8
So XMaskEvent is blocking, but whenever I press my mouse button it is not catching it. Shouldn't it unblock and get to the console.log line?
Do I need to run an event loop somehow in this thread?
Thanks
I'm not 100% sure here but I feel this could be your problem:
You probably can't do this from JavaScript without some extra precautions. JavaScript in the browser is single-threaded. That means you're holding a lock and no other JavaScript can run. Your problem is a) you're using threads and b) "If the event you requested is not in the queue, XMaskEvent flushes the output buffer and blocks until one is received." (see the man page)
That means XMaskEvent blocks since the button hasn't been pressed, yet. And your browser can't execute JavaScript anymore. If there is an event in the queue which would trigger some JavaScript, the browser will lock up.

Spring #Async cancel and start?

I have a spring MVC app where a user can kick off a Report generation via button click. This process could take few minutes ~ 10-20 mins.
I use springs #Async annotation around the service call so that report generation happens asynchronously. While I pop a message to user indicating job is currently running.
Now What I want to do is, if another user (Admin) can kick off Report generation via the button which should cancel/stop currently running #Async task and restart the new task.
To do this, I call the
.. ..
future = getCurrentTask(id); // returns the current task for given report id
if (!future.isDone())
future.cancel(true);
service.generateReport(id);
How can make it so that "service.generateReport" waits while the future cancel task kills all the running threads?
According to the documentation, after i call future.cancel(true), isDone will return true as well as isCancelled will return true. So there is no way of knowing the job is actually cancelled.
I can only start new report generation when old one is cancelled or completed so that it would not dirty data.
From documentation about cancel() method,
Subsequent calls to isCancelled() will always return true if this method returned true
Try this.
future = getCurrentTask(id); // returns the current task for given report id
if (!future.isDone()){
boolean terminatedImmediately=future.cancel(true);
if(terminatedImmediately)
service.generateReport(id);
else
//Inform user existing job couldn't be stopped.And to try again later
}
Assuming the code above runs in thread A, and your recently cancelled report is running in thread B, then you need thread A to stop before service.generateReport(id) and wait until thread B is completes / cancelled.
One approach to achieve this is to use Semaphore. Assuming there can be only 1 report running concurrently, first create a semaphore object acccessible by all threads (normally on the report runner service class)
Semaphore semaphore = new Semaphore(1);
At any point on your code where you need to run the report, call the acquire() method. This method will block until a permit is available. Similarly when the report execution is finished / cancelled, make sure release() is called. Release method will put the permit back and wakes up other waiting thread.
semaphore.acquire();
// run report..
semaphore.release();

android: AsyncTask onPostExecute keep working even if start new activity on doInBackground

i am building an application for clients to get questions from server and answer it, if the server doesn't have questions i want to go to new screen and print message that try again in few minutes, getting questions is in AsyncTask , if the server doesn't have questions , it will sends in the header of the responds, a header isFindAQuestion with the value false, here is the code on client to ensure if false , i print on LogCat and i see the message = false, but my problems that even if i start new activity with the intent, this activity keep working and show me exception and it is null pointer exception because on the onPostExceute will take a parmeter null and try to process it, i put finish() in the end of false statement but doesn't finish the activity
if (response.getFirstHeader("isFindAQuestion").getValue()
.toString().equals("false")) {
Log.d("message", "false");
Bundle basket = new Bundle();
basket.putString("Message", "sorry no enought questions");
Intent goToAnswerQuestion = new Intent(AnswerQuestion.this,
FinishTime.class);
goToAnswerQuestion.putExtras(basket);
startActivity(goToAnswerQuestion);
finish();
}
Editis it because AsyncTask is working on thread so if the activity is finished, that thread will keep working? and if so how can i stop that thread?
doInBackground is not executed in the UI thread, but in a separeted thread:
invoked on the background thread immediately after onPreExecute()
finishes executing. This step is used to perform background
computation that can take a long time.
If you want to stop your background operation and perform some activities on the UI thread the better thing is to call cancel() and then perform all the stuff you want in the onCancelled callback wich is executed on the UI thread.
From the AsyncTask documentation:
A task can be cancelled at any time by invoking cancel(boolean).
Invoking this method will cause subsequent calls to isCancelled() to return true. After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[]) returns.
To ensure that a task is cancelled as quickly as possible, you should always check the return value of isCancelled() periodically from doInBackground(Object[]), if possible (inside a loop for instance.)
protected void onCancelled (Result result)
Runs on the UI thread after cancel(boolean) is invoked and doInBackground(Object[]) has finished.
The default implementation simply invokes onCancelled() and ignores the result. If you write your own implementation, do not call super.onCancelled(result).

Cocoa: NSTimer gdb when invalidating

I'm using some timers and want the user to be able to cancel it before it's done, or remove it from a view after it has finished. Both of these things are supposed to be handled by a cancelAction method. If the timer hasn't finished, an if statement in cancelAction tells the timers to invalidate, makes them nil and removes the view displaying the time left. This works perfectly. If the timers already finished, cancelAction only removes the view, and does not try to invalidate them. But this doesn't seem to work. If I cancel before they finish, everything works, If I cancel after they finished, it throws an exception saying unrecognized selector sent to instance. Both timer were made using the scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: method
The difference between calling before or after they finished, is that if they finished, this method is run.
- (void)timerFinished:(id)sender {
[timer invalidate];
timer = nil;
[timerLabelUpdater invalidate];
timerLabelUpdater = nil;
}
This is where it gets strange. If I just remove [timerLaberUpdater invalidate] the method gets called and it gets removed. I don't want to remove that line because that timer counts down the time left and updates the view with the time left. If I don't invalidate it, it keeps counting down to the negatives, plus it takes up memory.
I sincerely have no idea why removing that line changes anything, both timers were called in the same way, and if I remove the other line, it still doesn't work, ONLY by removing that instruction does anything change.
I get EXC BAD ACCESS in gdb, which I think means the selector is sent to an instance that was released.
Thanks for the help.
if([timerLabelUpdater isValid])
[timerLabelUpdater invalidate];

Updating UI in Cocoa from another .m file

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.

Resources