How do I use DispatchGroup in background thread?
I have two functions (or tasks) that I want to run one after the other and i'm using DispatchGroup to track them and notify me when they're complete. Right now they're being done in the Main thread but I want to run these tasks in a background thread. How would I go about doing so? I've tried a few approaches but they either run simultaneously or I get an exception error after the first one completes. The following code performs the tasks one after the other but if I call Thread.current inside the functions I can see that they are being run in the Main thread.
@objc func doWorkFunctions(){
taskGroup.enter()
DispatchQueue.global(qos: .background).sync {
self.firstFunction {
self.taskGroup.leave()
}
}
taskGroup.enter()
DispatchQueue.global(qos: .background).sync {
self.secondFunction {
self.taskGroup.leave()
}
}
taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}
If I use the following code they are run simultaneously but in the background thread.
@objc func doWorkFunctions(){
taskGroup.enter()
DispatchQueue.global(qos: .background).async {
self.firstFunction {
self.taskGroup.leave()
}
}
taskGroup.enter()
DispatchQueue.global(qos: .background).async {
self.secondFunction {
self.taskGroup.leave()
}
}
taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}
I've been searching and searching but I can't seem to find an answer to my problem or clarity for that matter. Can someone provide some guidance as to what's going on here. These are the functions in question in case. They simulate a long task to practice tracking progress.
func firstFunction(completion: @escaping()->Void){
print(Thread.current)
if childProgressOne.isCancelled { return }
for i in 1...5 {
sleep(1)
childProgressOne.completedUnitCount = Int64(i * 20)
print("Child Progress One: (childProgressOne.fractionCompleted)")
print("Total Progress: (totalProgress.fractionCompleted)")
}
completion()
}
func secondFunction(completion: @escaping()->Void){
print(Thread.current)
if childProgressTwo.isCancelled { return }
for i in 1...5 {
sleep(1)
childProgressTwo.completedUnitCount = Int64(i * 20)
print("Child Progress Two: (childProgressTwo.fractionCompleted)")
print("Total Progress: (totalProgress.fractionCompleted)")
}
completion()
}
This also performs them in order but calling Thread.current inside the functions tells me they are being performed in the Main thread even though they are being called to a background thread.
@objc func doWorkFunctions(){
DispatchQueue.global(qos: .background).sync {
self.taskGroup.enter()
self.firstFunction {
self.taskGroup.leave()
}
self.taskGroup.enter()
self.secondFunction {
self.taskGroup.leave()
}
}
taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}
swift
|
show 3 more comments
I have two functions (or tasks) that I want to run one after the other and i'm using DispatchGroup to track them and notify me when they're complete. Right now they're being done in the Main thread but I want to run these tasks in a background thread. How would I go about doing so? I've tried a few approaches but they either run simultaneously or I get an exception error after the first one completes. The following code performs the tasks one after the other but if I call Thread.current inside the functions I can see that they are being run in the Main thread.
@objc func doWorkFunctions(){
taskGroup.enter()
DispatchQueue.global(qos: .background).sync {
self.firstFunction {
self.taskGroup.leave()
}
}
taskGroup.enter()
DispatchQueue.global(qos: .background).sync {
self.secondFunction {
self.taskGroup.leave()
}
}
taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}
If I use the following code they are run simultaneously but in the background thread.
@objc func doWorkFunctions(){
taskGroup.enter()
DispatchQueue.global(qos: .background).async {
self.firstFunction {
self.taskGroup.leave()
}
}
taskGroup.enter()
DispatchQueue.global(qos: .background).async {
self.secondFunction {
self.taskGroup.leave()
}
}
taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}
I've been searching and searching but I can't seem to find an answer to my problem or clarity for that matter. Can someone provide some guidance as to what's going on here. These are the functions in question in case. They simulate a long task to practice tracking progress.
func firstFunction(completion: @escaping()->Void){
print(Thread.current)
if childProgressOne.isCancelled { return }
for i in 1...5 {
sleep(1)
childProgressOne.completedUnitCount = Int64(i * 20)
print("Child Progress One: (childProgressOne.fractionCompleted)")
print("Total Progress: (totalProgress.fractionCompleted)")
}
completion()
}
func secondFunction(completion: @escaping()->Void){
print(Thread.current)
if childProgressTwo.isCancelled { return }
for i in 1...5 {
sleep(1)
childProgressTwo.completedUnitCount = Int64(i * 20)
print("Child Progress Two: (childProgressTwo.fractionCompleted)")
print("Total Progress: (totalProgress.fractionCompleted)")
}
completion()
}
This also performs them in order but calling Thread.current inside the functions tells me they are being performed in the Main thread even though they are being called to a background thread.
@objc func doWorkFunctions(){
DispatchQueue.global(qos: .background).sync {
self.taskGroup.enter()
self.firstFunction {
self.taskGroup.leave()
}
self.taskGroup.enter()
self.secondFunction {
self.taskGroup.leave()
}
}
taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}
swift
When you place them in the background thread, they will run simultaneously. I don't exactly get the problem.
– George_E
Dec 29 '18 at 18:12
@George_E I don't want them to run simultaneously. I want them to run in the background one after the other.
– Gustavo Picciuto
Dec 29 '18 at 18:14
Does it work if you use the first block of code with thesync
and put both in oneDispatchQueue
block?
– George_E
Dec 29 '18 at 18:18
That performs them one after the other but for some reason calling Thread.current inside the functions says it's still in the main thread.
– Gustavo Picciuto
Dec 29 '18 at 18:22
@George_E updated question with suggestion.
– Gustavo Picciuto
Dec 29 '18 at 18:25
|
show 3 more comments
I have two functions (or tasks) that I want to run one after the other and i'm using DispatchGroup to track them and notify me when they're complete. Right now they're being done in the Main thread but I want to run these tasks in a background thread. How would I go about doing so? I've tried a few approaches but they either run simultaneously or I get an exception error after the first one completes. The following code performs the tasks one after the other but if I call Thread.current inside the functions I can see that they are being run in the Main thread.
@objc func doWorkFunctions(){
taskGroup.enter()
DispatchQueue.global(qos: .background).sync {
self.firstFunction {
self.taskGroup.leave()
}
}
taskGroup.enter()
DispatchQueue.global(qos: .background).sync {
self.secondFunction {
self.taskGroup.leave()
}
}
taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}
If I use the following code they are run simultaneously but in the background thread.
@objc func doWorkFunctions(){
taskGroup.enter()
DispatchQueue.global(qos: .background).async {
self.firstFunction {
self.taskGroup.leave()
}
}
taskGroup.enter()
DispatchQueue.global(qos: .background).async {
self.secondFunction {
self.taskGroup.leave()
}
}
taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}
I've been searching and searching but I can't seem to find an answer to my problem or clarity for that matter. Can someone provide some guidance as to what's going on here. These are the functions in question in case. They simulate a long task to practice tracking progress.
func firstFunction(completion: @escaping()->Void){
print(Thread.current)
if childProgressOne.isCancelled { return }
for i in 1...5 {
sleep(1)
childProgressOne.completedUnitCount = Int64(i * 20)
print("Child Progress One: (childProgressOne.fractionCompleted)")
print("Total Progress: (totalProgress.fractionCompleted)")
}
completion()
}
func secondFunction(completion: @escaping()->Void){
print(Thread.current)
if childProgressTwo.isCancelled { return }
for i in 1...5 {
sleep(1)
childProgressTwo.completedUnitCount = Int64(i * 20)
print("Child Progress Two: (childProgressTwo.fractionCompleted)")
print("Total Progress: (totalProgress.fractionCompleted)")
}
completion()
}
This also performs them in order but calling Thread.current inside the functions tells me they are being performed in the Main thread even though they are being called to a background thread.
@objc func doWorkFunctions(){
DispatchQueue.global(qos: .background).sync {
self.taskGroup.enter()
self.firstFunction {
self.taskGroup.leave()
}
self.taskGroup.enter()
self.secondFunction {
self.taskGroup.leave()
}
}
taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}
swift
I have two functions (or tasks) that I want to run one after the other and i'm using DispatchGroup to track them and notify me when they're complete. Right now they're being done in the Main thread but I want to run these tasks in a background thread. How would I go about doing so? I've tried a few approaches but they either run simultaneously or I get an exception error after the first one completes. The following code performs the tasks one after the other but if I call Thread.current inside the functions I can see that they are being run in the Main thread.
@objc func doWorkFunctions(){
taskGroup.enter()
DispatchQueue.global(qos: .background).sync {
self.firstFunction {
self.taskGroup.leave()
}
}
taskGroup.enter()
DispatchQueue.global(qos: .background).sync {
self.secondFunction {
self.taskGroup.leave()
}
}
taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}
If I use the following code they are run simultaneously but in the background thread.
@objc func doWorkFunctions(){
taskGroup.enter()
DispatchQueue.global(qos: .background).async {
self.firstFunction {
self.taskGroup.leave()
}
}
taskGroup.enter()
DispatchQueue.global(qos: .background).async {
self.secondFunction {
self.taskGroup.leave()
}
}
taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}
I've been searching and searching but I can't seem to find an answer to my problem or clarity for that matter. Can someone provide some guidance as to what's going on here. These are the functions in question in case. They simulate a long task to practice tracking progress.
func firstFunction(completion: @escaping()->Void){
print(Thread.current)
if childProgressOne.isCancelled { return }
for i in 1...5 {
sleep(1)
childProgressOne.completedUnitCount = Int64(i * 20)
print("Child Progress One: (childProgressOne.fractionCompleted)")
print("Total Progress: (totalProgress.fractionCompleted)")
}
completion()
}
func secondFunction(completion: @escaping()->Void){
print(Thread.current)
if childProgressTwo.isCancelled { return }
for i in 1...5 {
sleep(1)
childProgressTwo.completedUnitCount = Int64(i * 20)
print("Child Progress Two: (childProgressTwo.fractionCompleted)")
print("Total Progress: (totalProgress.fractionCompleted)")
}
completion()
}
This also performs them in order but calling Thread.current inside the functions tells me they are being performed in the Main thread even though they are being called to a background thread.
@objc func doWorkFunctions(){
DispatchQueue.global(qos: .background).sync {
self.taskGroup.enter()
self.firstFunction {
self.taskGroup.leave()
}
self.taskGroup.enter()
self.secondFunction {
self.taskGroup.leave()
}
}
taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}
swift
swift
edited Dec 29 '18 at 18:24
Gustavo Picciuto
asked Dec 29 '18 at 18:05
Gustavo PicciutoGustavo Picciuto
86
86
When you place them in the background thread, they will run simultaneously. I don't exactly get the problem.
– George_E
Dec 29 '18 at 18:12
@George_E I don't want them to run simultaneously. I want them to run in the background one after the other.
– Gustavo Picciuto
Dec 29 '18 at 18:14
Does it work if you use the first block of code with thesync
and put both in oneDispatchQueue
block?
– George_E
Dec 29 '18 at 18:18
That performs them one after the other but for some reason calling Thread.current inside the functions says it's still in the main thread.
– Gustavo Picciuto
Dec 29 '18 at 18:22
@George_E updated question with suggestion.
– Gustavo Picciuto
Dec 29 '18 at 18:25
|
show 3 more comments
When you place them in the background thread, they will run simultaneously. I don't exactly get the problem.
– George_E
Dec 29 '18 at 18:12
@George_E I don't want them to run simultaneously. I want them to run in the background one after the other.
– Gustavo Picciuto
Dec 29 '18 at 18:14
Does it work if you use the first block of code with thesync
and put both in oneDispatchQueue
block?
– George_E
Dec 29 '18 at 18:18
That performs them one after the other but for some reason calling Thread.current inside the functions says it's still in the main thread.
– Gustavo Picciuto
Dec 29 '18 at 18:22
@George_E updated question with suggestion.
– Gustavo Picciuto
Dec 29 '18 at 18:25
When you place them in the background thread, they will run simultaneously. I don't exactly get the problem.
– George_E
Dec 29 '18 at 18:12
When you place them in the background thread, they will run simultaneously. I don't exactly get the problem.
– George_E
Dec 29 '18 at 18:12
@George_E I don't want them to run simultaneously. I want them to run in the background one after the other.
– Gustavo Picciuto
Dec 29 '18 at 18:14
@George_E I don't want them to run simultaneously. I want them to run in the background one after the other.
– Gustavo Picciuto
Dec 29 '18 at 18:14
Does it work if you use the first block of code with the
sync
and put both in one DispatchQueue
block?– George_E
Dec 29 '18 at 18:18
Does it work if you use the first block of code with the
sync
and put both in one DispatchQueue
block?– George_E
Dec 29 '18 at 18:18
That performs them one after the other but for some reason calling Thread.current inside the functions says it's still in the main thread.
– Gustavo Picciuto
Dec 29 '18 at 18:22
That performs them one after the other but for some reason calling Thread.current inside the functions says it's still in the main thread.
– Gustavo Picciuto
Dec 29 '18 at 18:22
@George_E updated question with suggestion.
– Gustavo Picciuto
Dec 29 '18 at 18:25
@George_E updated question with suggestion.
– Gustavo Picciuto
Dec 29 '18 at 18:25
|
show 3 more comments
3 Answers
3
active
oldest
votes
Given what you've described, I probably wouldn't use a dispatch group at all here. I'd just chain the methods:
@objc func doWorkFunctions() {
DispatchQueue.global(qos: .background).async {
self.firstFunction {
self.secondFunction {
DispatchQueue.main.async {
print("All tasks completed")
}
}
}
}
But assuming you have a good reason for a group here, what you need to do is to use .notify
to synchronize them. .notify
says "when the group is empty, submit this block to this queue."
@objc func doWorkFunctions(){
let queue = DispatchQueue.global(qos: .background)
taskGroup.enter()
queue.async {
self.firstFunction {
self.taskGroup.leave()
}
}
taskGroup.notify(queue: queue) {
self.taskGroup.enter()
self.secondFunction {
self.taskGroup.leave()
}
self.taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}
}
(You probably don't need taskGroup
to be an instance property here. You could make it a local variable and have fewer self.
references required. Each block has a reference to the group, so it will live until all the blocks have completed.)
Thank you for the reply Rob. The first worked out just fine for the intended purpose but the second one ended with an NSException. In both cases the functions were performed one after the other and in a background thread but in the second I get an error right after "All tasks completed" is printed out in the debugger. I suppose that I could use the first approach just fine for what i intended the code to perform which is basically tracking progress of both functions individually and overall. i'm still trying to wrap my head around DispatchGroups and how they are used and for what.
– Gustavo Picciuto
Dec 29 '18 at 19:17
What exception? (Did you remember the first.enter()
call at line 4? That's the most likely mistake.)
– Rob Napier
Dec 29 '18 at 21:24
I realized that the exception was being thrown because I was working in a class and there was an issue with the outlet from the button used to trigger the method. In a simple playground your solution works perfectly using groups. Thanks so much.
– Gustavo Picciuto
Dec 29 '18 at 23:54
add a comment |
If all you want to do is run two functions in serial in the background, then all you need to do is execute them in order in the same task within the same queue. There isn't any need to get fancy at all.
You can plug this into a playground and mess around with it:
import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
func firstFunction(completion: @escaping() -> Void) {
for i in 1...5 {
sleep(1)
print(i, Thread.current)
}
completion()
}
func secondFunction(completion: @escaping() -> Void) {
for i in 1...5 {
sleep(1)
print(i + 100, Thread.current)
}
completion()
}
func doWorkFunctions() {
let serialQueue = DispatchQueue(label: "serial")
//let concurrentQueue = DispatchQueue.global(qos: .default) <-- this will produce the same result
serialQueue.async {
firstFunction(completion: {
print("first function done")
})
secondFunction(completion: {
print("second function done")
})
}
}
doWorkFunctions()
Whether you execute these two functions in a serial queue or a concurrent queue, and whether you dispatch them in sync or async, is trivial as far as your question is concerned if you place them in the same task in the same queue. If you, however, separated the two functions into two separate tasks (or queues, for that matter), then serialization and concurrency become a factor. However, as a caveat, the term "concurrent" is relative. All tasks executed through dispatch queues (serial or concurrent) are concurrent to the main thread. But when we talk about them in the context of dispatch queues, we almost always mean concurrent to other tasks.
Read this to get a better understanding of what exactly queueing is: https://stackoverflow.com/a/53582047/9086770
Thanks so much! That information really helps out. Apples documentation is very limited in this regard. Your solution works perfectly for the intended purposes as well. I appreciate the help.
– Gustavo Picciuto
Dec 30 '18 at 2:44
Great read form the link. You summed it up perfectly and made it way more clear. Thanks again.
– Gustavo Picciuto
Dec 30 '18 at 3:23
It's surprising that this would work in live code. This example runscompletion
synchronously before returning, which means it's not a completion handler at all (completion handlers are run after an asynchronous operation completes, after returning). A more typical example would enclose the entire body offirstFunction
andsecondFunction
in aDispatchQueue.async
call on a queue you don't control, in which casesecondFunction
will start beforefirstFunction
finishes.
– Rob Napier
Dec 30 '18 at 16:07
Nothing surprising here--two functions were placed into a single task into the same queue and were executed in serial. There isn't anything that requires a completion block to be called on async operations (before or after the function returns) to be considered a completion block (true of all callbacks in all languages AFAIK). A completion block is nothing more than a block run after the operation’s main task is done. Whether they're typically used in async is something else, but their sole purpose is to notify the end of an operation--on the main thread, in the background, in sync, in async.
– bsod
Dec 30 '18 at 17:05
The common misconception here seems to be, that functionfirstFunction
and functionsecondFunction
ought to be asynchronous, which the@escaping
modifier for the completion handler indicates. However, the simulated functions are indeed synchronous. @nard ‘s approach only works for synchronous functions. Now, the questions is, are the actual functions asynchronous or synchronous? In case the actual functions are asynchronous @RobNapier's is the easiest solution.
– CouchDeveloper
Dec 31 '18 at 11:29
add a comment |
This solution is a combination of the first two answers. I used what @nard posted in the second answer but also using DispatchGroup. I realize in this scenario DispatchGroup isn't really needed but if in case it was, this would be a way to do it. Thanks to @Rob Napier and @nard for the guidance.
import UIKit
func workOne(completion: @escaping ()->Void){
print(Thread.current)
for i in 1...4{
sleep(1)
print(i)
}
completion()
}
func workTwo(completion: @escaping ()->Void){
print(Thread.current)
for i in 5...8{
sleep(1)
print(i)
}
completion()
}
func doWork(){
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
workOne {
dispatchGroup.leave()
}
dispatchGroup.enter()
workTwo {
dispatchGroup.leave()
}
dispatchGroup.notify(queue: .main) {
print(Thread.current)
print("completed!")
}
}
DispatchQueue.global(qos: .default).async {
doWork()
}
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53972081%2fhow-do-i-use-dispatchgroup-in-background-thread%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Given what you've described, I probably wouldn't use a dispatch group at all here. I'd just chain the methods:
@objc func doWorkFunctions() {
DispatchQueue.global(qos: .background).async {
self.firstFunction {
self.secondFunction {
DispatchQueue.main.async {
print("All tasks completed")
}
}
}
}
But assuming you have a good reason for a group here, what you need to do is to use .notify
to synchronize them. .notify
says "when the group is empty, submit this block to this queue."
@objc func doWorkFunctions(){
let queue = DispatchQueue.global(qos: .background)
taskGroup.enter()
queue.async {
self.firstFunction {
self.taskGroup.leave()
}
}
taskGroup.notify(queue: queue) {
self.taskGroup.enter()
self.secondFunction {
self.taskGroup.leave()
}
self.taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}
}
(You probably don't need taskGroup
to be an instance property here. You could make it a local variable and have fewer self.
references required. Each block has a reference to the group, so it will live until all the blocks have completed.)
Thank you for the reply Rob. The first worked out just fine for the intended purpose but the second one ended with an NSException. In both cases the functions were performed one after the other and in a background thread but in the second I get an error right after "All tasks completed" is printed out in the debugger. I suppose that I could use the first approach just fine for what i intended the code to perform which is basically tracking progress of both functions individually and overall. i'm still trying to wrap my head around DispatchGroups and how they are used and for what.
– Gustavo Picciuto
Dec 29 '18 at 19:17
What exception? (Did you remember the first.enter()
call at line 4? That's the most likely mistake.)
– Rob Napier
Dec 29 '18 at 21:24
I realized that the exception was being thrown because I was working in a class and there was an issue with the outlet from the button used to trigger the method. In a simple playground your solution works perfectly using groups. Thanks so much.
– Gustavo Picciuto
Dec 29 '18 at 23:54
add a comment |
Given what you've described, I probably wouldn't use a dispatch group at all here. I'd just chain the methods:
@objc func doWorkFunctions() {
DispatchQueue.global(qos: .background).async {
self.firstFunction {
self.secondFunction {
DispatchQueue.main.async {
print("All tasks completed")
}
}
}
}
But assuming you have a good reason for a group here, what you need to do is to use .notify
to synchronize them. .notify
says "when the group is empty, submit this block to this queue."
@objc func doWorkFunctions(){
let queue = DispatchQueue.global(qos: .background)
taskGroup.enter()
queue.async {
self.firstFunction {
self.taskGroup.leave()
}
}
taskGroup.notify(queue: queue) {
self.taskGroup.enter()
self.secondFunction {
self.taskGroup.leave()
}
self.taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}
}
(You probably don't need taskGroup
to be an instance property here. You could make it a local variable and have fewer self.
references required. Each block has a reference to the group, so it will live until all the blocks have completed.)
Thank you for the reply Rob. The first worked out just fine for the intended purpose but the second one ended with an NSException. In both cases the functions were performed one after the other and in a background thread but in the second I get an error right after "All tasks completed" is printed out in the debugger. I suppose that I could use the first approach just fine for what i intended the code to perform which is basically tracking progress of both functions individually and overall. i'm still trying to wrap my head around DispatchGroups and how they are used and for what.
– Gustavo Picciuto
Dec 29 '18 at 19:17
What exception? (Did you remember the first.enter()
call at line 4? That's the most likely mistake.)
– Rob Napier
Dec 29 '18 at 21:24
I realized that the exception was being thrown because I was working in a class and there was an issue with the outlet from the button used to trigger the method. In a simple playground your solution works perfectly using groups. Thanks so much.
– Gustavo Picciuto
Dec 29 '18 at 23:54
add a comment |
Given what you've described, I probably wouldn't use a dispatch group at all here. I'd just chain the methods:
@objc func doWorkFunctions() {
DispatchQueue.global(qos: .background).async {
self.firstFunction {
self.secondFunction {
DispatchQueue.main.async {
print("All tasks completed")
}
}
}
}
But assuming you have a good reason for a group here, what you need to do is to use .notify
to synchronize them. .notify
says "when the group is empty, submit this block to this queue."
@objc func doWorkFunctions(){
let queue = DispatchQueue.global(qos: .background)
taskGroup.enter()
queue.async {
self.firstFunction {
self.taskGroup.leave()
}
}
taskGroup.notify(queue: queue) {
self.taskGroup.enter()
self.secondFunction {
self.taskGroup.leave()
}
self.taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}
}
(You probably don't need taskGroup
to be an instance property here. You could make it a local variable and have fewer self.
references required. Each block has a reference to the group, so it will live until all the blocks have completed.)
Given what you've described, I probably wouldn't use a dispatch group at all here. I'd just chain the methods:
@objc func doWorkFunctions() {
DispatchQueue.global(qos: .background).async {
self.firstFunction {
self.secondFunction {
DispatchQueue.main.async {
print("All tasks completed")
}
}
}
}
But assuming you have a good reason for a group here, what you need to do is to use .notify
to synchronize them. .notify
says "when the group is empty, submit this block to this queue."
@objc func doWorkFunctions(){
let queue = DispatchQueue.global(qos: .background)
taskGroup.enter()
queue.async {
self.firstFunction {
self.taskGroup.leave()
}
}
taskGroup.notify(queue: queue) {
self.taskGroup.enter()
self.secondFunction {
self.taskGroup.leave()
}
self.taskGroup.notify(queue: .main) {
print("All tasks completed")
}
}
}
(You probably don't need taskGroup
to be an instance property here. You could make it a local variable and have fewer self.
references required. Each block has a reference to the group, so it will live until all the blocks have completed.)
edited Dec 29 '18 at 18:43
answered Dec 29 '18 at 18:37
Rob NapierRob Napier
200k28296422
200k28296422
Thank you for the reply Rob. The first worked out just fine for the intended purpose but the second one ended with an NSException. In both cases the functions were performed one after the other and in a background thread but in the second I get an error right after "All tasks completed" is printed out in the debugger. I suppose that I could use the first approach just fine for what i intended the code to perform which is basically tracking progress of both functions individually and overall. i'm still trying to wrap my head around DispatchGroups and how they are used and for what.
– Gustavo Picciuto
Dec 29 '18 at 19:17
What exception? (Did you remember the first.enter()
call at line 4? That's the most likely mistake.)
– Rob Napier
Dec 29 '18 at 21:24
I realized that the exception was being thrown because I was working in a class and there was an issue with the outlet from the button used to trigger the method. In a simple playground your solution works perfectly using groups. Thanks so much.
– Gustavo Picciuto
Dec 29 '18 at 23:54
add a comment |
Thank you for the reply Rob. The first worked out just fine for the intended purpose but the second one ended with an NSException. In both cases the functions were performed one after the other and in a background thread but in the second I get an error right after "All tasks completed" is printed out in the debugger. I suppose that I could use the first approach just fine for what i intended the code to perform which is basically tracking progress of both functions individually and overall. i'm still trying to wrap my head around DispatchGroups and how they are used and for what.
– Gustavo Picciuto
Dec 29 '18 at 19:17
What exception? (Did you remember the first.enter()
call at line 4? That's the most likely mistake.)
– Rob Napier
Dec 29 '18 at 21:24
I realized that the exception was being thrown because I was working in a class and there was an issue with the outlet from the button used to trigger the method. In a simple playground your solution works perfectly using groups. Thanks so much.
– Gustavo Picciuto
Dec 29 '18 at 23:54
Thank you for the reply Rob. The first worked out just fine for the intended purpose but the second one ended with an NSException. In both cases the functions were performed one after the other and in a background thread but in the second I get an error right after "All tasks completed" is printed out in the debugger. I suppose that I could use the first approach just fine for what i intended the code to perform which is basically tracking progress of both functions individually and overall. i'm still trying to wrap my head around DispatchGroups and how they are used and for what.
– Gustavo Picciuto
Dec 29 '18 at 19:17
Thank you for the reply Rob. The first worked out just fine for the intended purpose but the second one ended with an NSException. In both cases the functions were performed one after the other and in a background thread but in the second I get an error right after "All tasks completed" is printed out in the debugger. I suppose that I could use the first approach just fine for what i intended the code to perform which is basically tracking progress of both functions individually and overall. i'm still trying to wrap my head around DispatchGroups and how they are used and for what.
– Gustavo Picciuto
Dec 29 '18 at 19:17
What exception? (Did you remember the first
.enter()
call at line 4? That's the most likely mistake.)– Rob Napier
Dec 29 '18 at 21:24
What exception? (Did you remember the first
.enter()
call at line 4? That's the most likely mistake.)– Rob Napier
Dec 29 '18 at 21:24
I realized that the exception was being thrown because I was working in a class and there was an issue with the outlet from the button used to trigger the method. In a simple playground your solution works perfectly using groups. Thanks so much.
– Gustavo Picciuto
Dec 29 '18 at 23:54
I realized that the exception was being thrown because I was working in a class and there was an issue with the outlet from the button used to trigger the method. In a simple playground your solution works perfectly using groups. Thanks so much.
– Gustavo Picciuto
Dec 29 '18 at 23:54
add a comment |
If all you want to do is run two functions in serial in the background, then all you need to do is execute them in order in the same task within the same queue. There isn't any need to get fancy at all.
You can plug this into a playground and mess around with it:
import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
func firstFunction(completion: @escaping() -> Void) {
for i in 1...5 {
sleep(1)
print(i, Thread.current)
}
completion()
}
func secondFunction(completion: @escaping() -> Void) {
for i in 1...5 {
sleep(1)
print(i + 100, Thread.current)
}
completion()
}
func doWorkFunctions() {
let serialQueue = DispatchQueue(label: "serial")
//let concurrentQueue = DispatchQueue.global(qos: .default) <-- this will produce the same result
serialQueue.async {
firstFunction(completion: {
print("first function done")
})
secondFunction(completion: {
print("second function done")
})
}
}
doWorkFunctions()
Whether you execute these two functions in a serial queue or a concurrent queue, and whether you dispatch them in sync or async, is trivial as far as your question is concerned if you place them in the same task in the same queue. If you, however, separated the two functions into two separate tasks (or queues, for that matter), then serialization and concurrency become a factor. However, as a caveat, the term "concurrent" is relative. All tasks executed through dispatch queues (serial or concurrent) are concurrent to the main thread. But when we talk about them in the context of dispatch queues, we almost always mean concurrent to other tasks.
Read this to get a better understanding of what exactly queueing is: https://stackoverflow.com/a/53582047/9086770
Thanks so much! That information really helps out. Apples documentation is very limited in this regard. Your solution works perfectly for the intended purposes as well. I appreciate the help.
– Gustavo Picciuto
Dec 30 '18 at 2:44
Great read form the link. You summed it up perfectly and made it way more clear. Thanks again.
– Gustavo Picciuto
Dec 30 '18 at 3:23
It's surprising that this would work in live code. This example runscompletion
synchronously before returning, which means it's not a completion handler at all (completion handlers are run after an asynchronous operation completes, after returning). A more typical example would enclose the entire body offirstFunction
andsecondFunction
in aDispatchQueue.async
call on a queue you don't control, in which casesecondFunction
will start beforefirstFunction
finishes.
– Rob Napier
Dec 30 '18 at 16:07
Nothing surprising here--two functions were placed into a single task into the same queue and were executed in serial. There isn't anything that requires a completion block to be called on async operations (before or after the function returns) to be considered a completion block (true of all callbacks in all languages AFAIK). A completion block is nothing more than a block run after the operation’s main task is done. Whether they're typically used in async is something else, but their sole purpose is to notify the end of an operation--on the main thread, in the background, in sync, in async.
– bsod
Dec 30 '18 at 17:05
The common misconception here seems to be, that functionfirstFunction
and functionsecondFunction
ought to be asynchronous, which the@escaping
modifier for the completion handler indicates. However, the simulated functions are indeed synchronous. @nard ‘s approach only works for synchronous functions. Now, the questions is, are the actual functions asynchronous or synchronous? In case the actual functions are asynchronous @RobNapier's is the easiest solution.
– CouchDeveloper
Dec 31 '18 at 11:29
add a comment |
If all you want to do is run two functions in serial in the background, then all you need to do is execute them in order in the same task within the same queue. There isn't any need to get fancy at all.
You can plug this into a playground and mess around with it:
import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
func firstFunction(completion: @escaping() -> Void) {
for i in 1...5 {
sleep(1)
print(i, Thread.current)
}
completion()
}
func secondFunction(completion: @escaping() -> Void) {
for i in 1...5 {
sleep(1)
print(i + 100, Thread.current)
}
completion()
}
func doWorkFunctions() {
let serialQueue = DispatchQueue(label: "serial")
//let concurrentQueue = DispatchQueue.global(qos: .default) <-- this will produce the same result
serialQueue.async {
firstFunction(completion: {
print("first function done")
})
secondFunction(completion: {
print("second function done")
})
}
}
doWorkFunctions()
Whether you execute these two functions in a serial queue or a concurrent queue, and whether you dispatch them in sync or async, is trivial as far as your question is concerned if you place them in the same task in the same queue. If you, however, separated the two functions into two separate tasks (or queues, for that matter), then serialization and concurrency become a factor. However, as a caveat, the term "concurrent" is relative. All tasks executed through dispatch queues (serial or concurrent) are concurrent to the main thread. But when we talk about them in the context of dispatch queues, we almost always mean concurrent to other tasks.
Read this to get a better understanding of what exactly queueing is: https://stackoverflow.com/a/53582047/9086770
Thanks so much! That information really helps out. Apples documentation is very limited in this regard. Your solution works perfectly for the intended purposes as well. I appreciate the help.
– Gustavo Picciuto
Dec 30 '18 at 2:44
Great read form the link. You summed it up perfectly and made it way more clear. Thanks again.
– Gustavo Picciuto
Dec 30 '18 at 3:23
It's surprising that this would work in live code. This example runscompletion
synchronously before returning, which means it's not a completion handler at all (completion handlers are run after an asynchronous operation completes, after returning). A more typical example would enclose the entire body offirstFunction
andsecondFunction
in aDispatchQueue.async
call on a queue you don't control, in which casesecondFunction
will start beforefirstFunction
finishes.
– Rob Napier
Dec 30 '18 at 16:07
Nothing surprising here--two functions were placed into a single task into the same queue and were executed in serial. There isn't anything that requires a completion block to be called on async operations (before or after the function returns) to be considered a completion block (true of all callbacks in all languages AFAIK). A completion block is nothing more than a block run after the operation’s main task is done. Whether they're typically used in async is something else, but their sole purpose is to notify the end of an operation--on the main thread, in the background, in sync, in async.
– bsod
Dec 30 '18 at 17:05
The common misconception here seems to be, that functionfirstFunction
and functionsecondFunction
ought to be asynchronous, which the@escaping
modifier for the completion handler indicates. However, the simulated functions are indeed synchronous. @nard ‘s approach only works for synchronous functions. Now, the questions is, are the actual functions asynchronous or synchronous? In case the actual functions are asynchronous @RobNapier's is the easiest solution.
– CouchDeveloper
Dec 31 '18 at 11:29
add a comment |
If all you want to do is run two functions in serial in the background, then all you need to do is execute them in order in the same task within the same queue. There isn't any need to get fancy at all.
You can plug this into a playground and mess around with it:
import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
func firstFunction(completion: @escaping() -> Void) {
for i in 1...5 {
sleep(1)
print(i, Thread.current)
}
completion()
}
func secondFunction(completion: @escaping() -> Void) {
for i in 1...5 {
sleep(1)
print(i + 100, Thread.current)
}
completion()
}
func doWorkFunctions() {
let serialQueue = DispatchQueue(label: "serial")
//let concurrentQueue = DispatchQueue.global(qos: .default) <-- this will produce the same result
serialQueue.async {
firstFunction(completion: {
print("first function done")
})
secondFunction(completion: {
print("second function done")
})
}
}
doWorkFunctions()
Whether you execute these two functions in a serial queue or a concurrent queue, and whether you dispatch them in sync or async, is trivial as far as your question is concerned if you place them in the same task in the same queue. If you, however, separated the two functions into two separate tasks (or queues, for that matter), then serialization and concurrency become a factor. However, as a caveat, the term "concurrent" is relative. All tasks executed through dispatch queues (serial or concurrent) are concurrent to the main thread. But when we talk about them in the context of dispatch queues, we almost always mean concurrent to other tasks.
Read this to get a better understanding of what exactly queueing is: https://stackoverflow.com/a/53582047/9086770
If all you want to do is run two functions in serial in the background, then all you need to do is execute them in order in the same task within the same queue. There isn't any need to get fancy at all.
You can plug this into a playground and mess around with it:
import UIKit
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
func firstFunction(completion: @escaping() -> Void) {
for i in 1...5 {
sleep(1)
print(i, Thread.current)
}
completion()
}
func secondFunction(completion: @escaping() -> Void) {
for i in 1...5 {
sleep(1)
print(i + 100, Thread.current)
}
completion()
}
func doWorkFunctions() {
let serialQueue = DispatchQueue(label: "serial")
//let concurrentQueue = DispatchQueue.global(qos: .default) <-- this will produce the same result
serialQueue.async {
firstFunction(completion: {
print("first function done")
})
secondFunction(completion: {
print("second function done")
})
}
}
doWorkFunctions()
Whether you execute these two functions in a serial queue or a concurrent queue, and whether you dispatch them in sync or async, is trivial as far as your question is concerned if you place them in the same task in the same queue. If you, however, separated the two functions into two separate tasks (or queues, for that matter), then serialization and concurrency become a factor. However, as a caveat, the term "concurrent" is relative. All tasks executed through dispatch queues (serial or concurrent) are concurrent to the main thread. But when we talk about them in the context of dispatch queues, we almost always mean concurrent to other tasks.
Read this to get a better understanding of what exactly queueing is: https://stackoverflow.com/a/53582047/9086770
answered Dec 29 '18 at 19:01
bsodbsod
2,1561820
2,1561820
Thanks so much! That information really helps out. Apples documentation is very limited in this regard. Your solution works perfectly for the intended purposes as well. I appreciate the help.
– Gustavo Picciuto
Dec 30 '18 at 2:44
Great read form the link. You summed it up perfectly and made it way more clear. Thanks again.
– Gustavo Picciuto
Dec 30 '18 at 3:23
It's surprising that this would work in live code. This example runscompletion
synchronously before returning, which means it's not a completion handler at all (completion handlers are run after an asynchronous operation completes, after returning). A more typical example would enclose the entire body offirstFunction
andsecondFunction
in aDispatchQueue.async
call on a queue you don't control, in which casesecondFunction
will start beforefirstFunction
finishes.
– Rob Napier
Dec 30 '18 at 16:07
Nothing surprising here--two functions were placed into a single task into the same queue and were executed in serial. There isn't anything that requires a completion block to be called on async operations (before or after the function returns) to be considered a completion block (true of all callbacks in all languages AFAIK). A completion block is nothing more than a block run after the operation’s main task is done. Whether they're typically used in async is something else, but their sole purpose is to notify the end of an operation--on the main thread, in the background, in sync, in async.
– bsod
Dec 30 '18 at 17:05
The common misconception here seems to be, that functionfirstFunction
and functionsecondFunction
ought to be asynchronous, which the@escaping
modifier for the completion handler indicates. However, the simulated functions are indeed synchronous. @nard ‘s approach only works for synchronous functions. Now, the questions is, are the actual functions asynchronous or synchronous? In case the actual functions are asynchronous @RobNapier's is the easiest solution.
– CouchDeveloper
Dec 31 '18 at 11:29
add a comment |
Thanks so much! That information really helps out. Apples documentation is very limited in this regard. Your solution works perfectly for the intended purposes as well. I appreciate the help.
– Gustavo Picciuto
Dec 30 '18 at 2:44
Great read form the link. You summed it up perfectly and made it way more clear. Thanks again.
– Gustavo Picciuto
Dec 30 '18 at 3:23
It's surprising that this would work in live code. This example runscompletion
synchronously before returning, which means it's not a completion handler at all (completion handlers are run after an asynchronous operation completes, after returning). A more typical example would enclose the entire body offirstFunction
andsecondFunction
in aDispatchQueue.async
call on a queue you don't control, in which casesecondFunction
will start beforefirstFunction
finishes.
– Rob Napier
Dec 30 '18 at 16:07
Nothing surprising here--two functions were placed into a single task into the same queue and were executed in serial. There isn't anything that requires a completion block to be called on async operations (before or after the function returns) to be considered a completion block (true of all callbacks in all languages AFAIK). A completion block is nothing more than a block run after the operation’s main task is done. Whether they're typically used in async is something else, but their sole purpose is to notify the end of an operation--on the main thread, in the background, in sync, in async.
– bsod
Dec 30 '18 at 17:05
The common misconception here seems to be, that functionfirstFunction
and functionsecondFunction
ought to be asynchronous, which the@escaping
modifier for the completion handler indicates. However, the simulated functions are indeed synchronous. @nard ‘s approach only works for synchronous functions. Now, the questions is, are the actual functions asynchronous or synchronous? In case the actual functions are asynchronous @RobNapier's is the easiest solution.
– CouchDeveloper
Dec 31 '18 at 11:29
Thanks so much! That information really helps out. Apples documentation is very limited in this regard. Your solution works perfectly for the intended purposes as well. I appreciate the help.
– Gustavo Picciuto
Dec 30 '18 at 2:44
Thanks so much! That information really helps out. Apples documentation is very limited in this regard. Your solution works perfectly for the intended purposes as well. I appreciate the help.
– Gustavo Picciuto
Dec 30 '18 at 2:44
Great read form the link. You summed it up perfectly and made it way more clear. Thanks again.
– Gustavo Picciuto
Dec 30 '18 at 3:23
Great read form the link. You summed it up perfectly and made it way more clear. Thanks again.
– Gustavo Picciuto
Dec 30 '18 at 3:23
It's surprising that this would work in live code. This example runs
completion
synchronously before returning, which means it's not a completion handler at all (completion handlers are run after an asynchronous operation completes, after returning). A more typical example would enclose the entire body of firstFunction
and secondFunction
in a DispatchQueue.async
call on a queue you don't control, in which case secondFunction
will start before firstFunction
finishes.– Rob Napier
Dec 30 '18 at 16:07
It's surprising that this would work in live code. This example runs
completion
synchronously before returning, which means it's not a completion handler at all (completion handlers are run after an asynchronous operation completes, after returning). A more typical example would enclose the entire body of firstFunction
and secondFunction
in a DispatchQueue.async
call on a queue you don't control, in which case secondFunction
will start before firstFunction
finishes.– Rob Napier
Dec 30 '18 at 16:07
Nothing surprising here--two functions were placed into a single task into the same queue and were executed in serial. There isn't anything that requires a completion block to be called on async operations (before or after the function returns) to be considered a completion block (true of all callbacks in all languages AFAIK). A completion block is nothing more than a block run after the operation’s main task is done. Whether they're typically used in async is something else, but their sole purpose is to notify the end of an operation--on the main thread, in the background, in sync, in async.
– bsod
Dec 30 '18 at 17:05
Nothing surprising here--two functions were placed into a single task into the same queue and were executed in serial. There isn't anything that requires a completion block to be called on async operations (before or after the function returns) to be considered a completion block (true of all callbacks in all languages AFAIK). A completion block is nothing more than a block run after the operation’s main task is done. Whether they're typically used in async is something else, but their sole purpose is to notify the end of an operation--on the main thread, in the background, in sync, in async.
– bsod
Dec 30 '18 at 17:05
The common misconception here seems to be, that function
firstFunction
and function secondFunction
ought to be asynchronous, which the @escaping
modifier for the completion handler indicates. However, the simulated functions are indeed synchronous. @nard ‘s approach only works for synchronous functions. Now, the questions is, are the actual functions asynchronous or synchronous? In case the actual functions are asynchronous @RobNapier's is the easiest solution.– CouchDeveloper
Dec 31 '18 at 11:29
The common misconception here seems to be, that function
firstFunction
and function secondFunction
ought to be asynchronous, which the @escaping
modifier for the completion handler indicates. However, the simulated functions are indeed synchronous. @nard ‘s approach only works for synchronous functions. Now, the questions is, are the actual functions asynchronous or synchronous? In case the actual functions are asynchronous @RobNapier's is the easiest solution.– CouchDeveloper
Dec 31 '18 at 11:29
add a comment |
This solution is a combination of the first two answers. I used what @nard posted in the second answer but also using DispatchGroup. I realize in this scenario DispatchGroup isn't really needed but if in case it was, this would be a way to do it. Thanks to @Rob Napier and @nard for the guidance.
import UIKit
func workOne(completion: @escaping ()->Void){
print(Thread.current)
for i in 1...4{
sleep(1)
print(i)
}
completion()
}
func workTwo(completion: @escaping ()->Void){
print(Thread.current)
for i in 5...8{
sleep(1)
print(i)
}
completion()
}
func doWork(){
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
workOne {
dispatchGroup.leave()
}
dispatchGroup.enter()
workTwo {
dispatchGroup.leave()
}
dispatchGroup.notify(queue: .main) {
print(Thread.current)
print("completed!")
}
}
DispatchQueue.global(qos: .default).async {
doWork()
}
add a comment |
This solution is a combination of the first two answers. I used what @nard posted in the second answer but also using DispatchGroup. I realize in this scenario DispatchGroup isn't really needed but if in case it was, this would be a way to do it. Thanks to @Rob Napier and @nard for the guidance.
import UIKit
func workOne(completion: @escaping ()->Void){
print(Thread.current)
for i in 1...4{
sleep(1)
print(i)
}
completion()
}
func workTwo(completion: @escaping ()->Void){
print(Thread.current)
for i in 5...8{
sleep(1)
print(i)
}
completion()
}
func doWork(){
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
workOne {
dispatchGroup.leave()
}
dispatchGroup.enter()
workTwo {
dispatchGroup.leave()
}
dispatchGroup.notify(queue: .main) {
print(Thread.current)
print("completed!")
}
}
DispatchQueue.global(qos: .default).async {
doWork()
}
add a comment |
This solution is a combination of the first two answers. I used what @nard posted in the second answer but also using DispatchGroup. I realize in this scenario DispatchGroup isn't really needed but if in case it was, this would be a way to do it. Thanks to @Rob Napier and @nard for the guidance.
import UIKit
func workOne(completion: @escaping ()->Void){
print(Thread.current)
for i in 1...4{
sleep(1)
print(i)
}
completion()
}
func workTwo(completion: @escaping ()->Void){
print(Thread.current)
for i in 5...8{
sleep(1)
print(i)
}
completion()
}
func doWork(){
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
workOne {
dispatchGroup.leave()
}
dispatchGroup.enter()
workTwo {
dispatchGroup.leave()
}
dispatchGroup.notify(queue: .main) {
print(Thread.current)
print("completed!")
}
}
DispatchQueue.global(qos: .default).async {
doWork()
}
This solution is a combination of the first two answers. I used what @nard posted in the second answer but also using DispatchGroup. I realize in this scenario DispatchGroup isn't really needed but if in case it was, this would be a way to do it. Thanks to @Rob Napier and @nard for the guidance.
import UIKit
func workOne(completion: @escaping ()->Void){
print(Thread.current)
for i in 1...4{
sleep(1)
print(i)
}
completion()
}
func workTwo(completion: @escaping ()->Void){
print(Thread.current)
for i in 5...8{
sleep(1)
print(i)
}
completion()
}
func doWork(){
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
workOne {
dispatchGroup.leave()
}
dispatchGroup.enter()
workTwo {
dispatchGroup.leave()
}
dispatchGroup.notify(queue: .main) {
print(Thread.current)
print("completed!")
}
}
DispatchQueue.global(qos: .default).async {
doWork()
}
answered Dec 30 '18 at 3:58
Gustavo PicciutoGustavo Picciuto
86
86
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53972081%2fhow-do-i-use-dispatchgroup-in-background-thread%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
When you place them in the background thread, they will run simultaneously. I don't exactly get the problem.
– George_E
Dec 29 '18 at 18:12
@George_E I don't want them to run simultaneously. I want them to run in the background one after the other.
– Gustavo Picciuto
Dec 29 '18 at 18:14
Does it work if you use the first block of code with the
sync
and put both in oneDispatchQueue
block?– George_E
Dec 29 '18 at 18:18
That performs them one after the other but for some reason calling Thread.current inside the functions says it's still in the main thread.
– Gustavo Picciuto
Dec 29 '18 at 18:22
@George_E updated question with suggestion.
– Gustavo Picciuto
Dec 29 '18 at 18:25