How to callbacks Serial Dispatch Queues in GCD - iphone

dispatch_queue_t myCustomQueue;
myCustomQueue=dispatch_queue_create("com.example.MyCustomQueue", nil);
dispatch_async(myCustomQueue, ^{
printf("Do some work here.\n");
});
dispatch_async(myCustomQueue, ^{
printf("Do Some Things here!!!\n");
});
I implemented Serial Dispatch Queues,I assigned two task after that i want to callback a task that notify the whole application.How do this?.

Related

swift async function is being run on the main thread in some cases when run from task

In this case the async function reads a file and returns the parsed contents.
In my view I want to load the contents off of the main thread, and then update the view once complete.
I've used this pattern in various places and noticed that in some cases the async call is on the main thread (by debugging) while in others it is on the Thread 4 Queue : com.apple.root.user-initiated-qos.cooperative (concurrent) thread
For example:
struct MyView: View {
#State var data = "some data"
var body: some View {
Button("refresh") {
// when the button is pressed refresh it
Task {
await refresh()
}
}.task {
// when the view appears
await refresh()
}
Text("the data is \(data)") // write the data which was refreshed async
}
}
func refresh() async {
do {
let res = try await anotherAyncFunction()
data = res // this is presumably wrong and off the main thread - obviously might not be correct but leave here for debug as well
} catch {
print("got error \(error)")
}
}
I created several different views using a similar pattern (.task block calling async functions)
In some cases the functions are long running (reading from disk) and that is happening on the main thread
Change Task { to Task.detached {.
From the Swift Language Guide:
To create an unstructured task that runs on the current actor, call the Task.init(priority:operation:) initializer. To create an unstructured task that’s not part of the current actor, known more specifically as a detached task, call the Task.detached(priority:operation:) class method.
When you call Task.init, the asynchronous code runs on the current actor, which, in this context is the main actor. This has the result of blocking the main thread.
By calling Task.detached, you allow the asynchronous work to happen off the main thread.
Using Swift structured concurrency, to run code on a background thread, use a detached task or (better) an actor.

How to guarantee one function runs after another in the Grand Central Dispatch?

Basically, I want to upload some images before I run other functions that rely on the image being uploaded. I think I may have a misunderstanding of what GCD is/how the threads work. I want function 1 and 2 to happen AFTER I upload the images. They are both quick to execute but rely heavily on the upload images to be complete. Maybe I shouldn't use GCD (as I want to implement a waiting indicator)? I just can't seem to get this to execute properly
if goToHome {
DispatchQueue.global().async {
DispatchQueue.main.sync {
self.uploadImages() // Uploads the images, takes a good amount of time to execute
function1()
function2()
}
}
Functions 1 and 2 keep running before the upload images get completed as they take much less time to execute.
The basic pattern in Swift is to do work such as uploading on a background thread, then call a completion function on the main thread and continue work based on whether or not your upload finished successfully.
Generally you'll call back onto the main thread in case you need to do something with the user interface such as setting a progress indicator (which has to happen on the main thread).
So something like this:
func uploadInBackground(_ images: [Image], completion: #escaping (_ success: Bool) -> Void) {
DispatchQueue.global(qos: .background).async {
var success = true
// upload the images but stop on any error
for image in images {
success = uploadImage(image) // upload your images somehow
guard success else { break }
}
DispatchQueue.main.async {
completion(success)
}
}
}
func mainThreadUploader() {
let images = [Image(), Image()] // get your images from somewhere
// we are on the main thread where UI operations are ok, so:
startProgressIndicator()
uploadInBackground(images) { success in
// this callback is called on the main thread, so:
stopProgressIndicator()
guard success else { return }
// images uploaded ok, so proceed with functions that depend on
// the upload(s) completing successfully:
function1()
function2()
}
}
Despite running the upload image function in the main queue, the upload image function itself is running operations in a background queue. To fix this, possible strategies would be:
use a completion handler with the image upload, likely the easiest to implement depending on the implementation of the self.uploadImages() function
make the image uploading happen on the main thread, which is likely hard to implement and inadvisable
use a dispatch group, which I personally have less experience with but is an option

GWT Timer.scheduleRepeating keeps firing after call to cancel()

The GWT timer I use in my application doesn't seem to respond to a call to cancel().
I see new server calls being fired, even after cancel() is reached.
com.google.gwt.user.client.Timer t = new com.google.gwt.user.client.Timer() {
#Override
public void run() {
myService.poll(result.getKey(), new HappyAsyncCallback<JobResult>() {
#Override
public void onSuccess(JobResult result) {
if (result.getUuid() != null && !result.getUuid().isEmpty()) {
Window.alert("Done! Cancelling...");
cancel();
}
}
});
}
};
t.scheduleRepeating(5000);
I read these similar issues, but haven't been able to use these issues to my advantage unfortunately.
GWT Timer cancel not working
Can't cancel repeat timer in GWT
I have been fooled by my own application here. We are doing a really lengthy batch process on the server and during this process the Timer will fire multiple calls to poll(). When the cancel() method is reached, these calls are still returning from the server :) Thanks for your suggestions, Manolo.

Display.asyncExec vs Display.timerExec

I was hoping that Display.timerExec(int,Runnable) was much the same as Display.asyncExec(Runnable) but with the specified delay. However it appears that Display.timerExec can only be executed on the GUI thread, as its 1st line is a call to checkDevice(). This throws an exception if you're not running in a GUI thread.
Can anyone suggest a means to using Display.asyncExec() but with a delay preceding execution?
You can first switch to the GUI thread with asyncExec, then schedule a timer action with timerExec. These two methods are similar in that they both execute some action, but asyncExec only switches thread, timeExec only schedules an action for the GUI thread.
display.asyncExec(() -> display.timerExec(100, () -> doThings()));
This uses lambda expressions, which where introduced in Java 8.
With Java 7 or earlier one has to write it with anonymous classes like this:
display.asyncExec(new Runnable() {
public void run() {
display.timerExec(100, new Runnable() {
public void run() {
doThings();
}
});
}
});

UIAlertView: wait_fences: failed to receive reply: 10004003

I'm running a web request in the background and I want the user to be able to cancel this request. I use a UIActionSheet with a Cancel button while the web request is running. When the web request returns an error, I close the UIActionSheet by calling DismissWithClickedButtonIndex(0, true). Then I show a UIAlertView with an error message and the option to cancel or retry the web request.
Everything works fine most of the time, but sometimes I get the "wait_fences: failed to receive reply: 10004003" message in the console output window and incidentally there is some strange UI-behaviour.
I did some searching and found out that this is caused by something like the underlaying view cannot get control before the control is transferred to the UIAlertView. Some people suggested to delay showing the AlertView by using PerformSelector. Is this the right solution? If so, how do I transfer the Show method of the UIAlertView to the first parameter of the PerformSelector method?
Currently I use this solution for the delay:
private void StartAfterParentViewUpdate(NSAction action)
{
NSAction delayedAction = () => BeginInvokeOnMainThread(action);
NSTimer.CreateScheduledTimer(new TimeSpan(0, 0, 0, 0, 200), delayedAction);
}
This way I can call StartAfterParentViewUpdate(_alertView.Show) and I guess it will run on the main UI thread as soon as the thread can handle it. Is this correct or is there a better way to solve this problem?
To answer my own question: the solution works good, I never saw the wait_fences message again. I made a static helper to use from any class:
public static class UIHelper
{
public static void StartAfterParentViewUpdate(NSObject parent, NSAction action)
{
NSTimer.CreateScheduledTimer(new TimeSpan(0, 0, 0, 0, 100), () => parent.BeginInvokeOnMainThread(action));
}
// Use this helper method only when action is a non-static member of an object.
public static void StartAfterParentViewUpdate(NSAction action)
{
StartAfterParentViewUpdate((NSObject)action.Target, action);
}
}
If you need to delay the call to a method with parameters, use an anonymous delegate. Example:
NSAction action = () => { viewController.NavigationController.PopViewControllerAnimated(true); };
UIHelper.StartAfterParentViewUpdate(viewController, action);