টাস্ক শেষ না হওয়া পর্যন্ত অপেক্ষা করা হচ্ছে


101

ডিসপ্যাচকিউয়ে কাজ শেষ না হওয়া পর্যন্ত আমি কীভাবে আমার কোডটি অপেক্ষা করতে পারি? এটির কোনও কমপ্লেইশনহ্যান্ডলার বা কিছু দরকার?

func myFunction() {
    var a: Int?

    DispatchQueue.main.async {
        var b: Int = 3
        a = b
    }

    // wait until the task finishes, then print 

    print(a) // - this will contain nil, of course, because it
             // will execute before the code above

}

আমি এক্সকোড 8.2 ব্যবহার করছি এবং সুইফ্ট 3-এ লিখছি।

উত্তর:


239

DispatchGroupএটি অর্জন করতে এস ব্যবহার করুন । গোষ্ঠীর কল enter()এবং leave()কলগুলি ভারসাম্যহীন হলে আপনি বিজ্ঞপ্তি পেতে পারেন :

func myFunction() {
    var a: Int?

    let group = DispatchGroup()
    group.enter()

    DispatchQueue.main.async {
        a = 1
        group.leave()
    }

    // does not wait. But the code in notify() gets run 
    // after enter() and leave() calls are balanced

    group.notify(queue: .main) {
        print(a)
    }
}

অথবা আপনি অপেক্ষা করতে পারেন:

func myFunction() {
    var a: Int?

    let group = DispatchGroup()
    group.enter()

    // avoid deadlocks by not using .main queue here
    DispatchQueue.global(attributes: .qosDefault).async {
        a = 1
        group.leave()
    }

    // wait ...
    group.wait()

    print(a) // you could also `return a` here
}

দ্রষ্টব্য : group.wait()বর্তমান সারিটি অবরুদ্ধ করে (সম্ভবত আপনার ক্ষেত্রে প্রধান সারি), তাই dispatch.asyncকোনও অচলাবস্থা এড়াতে আপনাকে অন্য একটি সারিতে (উপরের নমুনা কোডের মতো) যেতে হবে ।


আমি অন্য ক্লাসে একটি ফাংশন সম্পাদন করতে চাই তবে আমি সেই ফাংশনটি শেষ করার জন্য অপেক্ষা করতে চাই এবং তারপরে বর্তমান ক্লাসে কীভাবে এটি পরিচালনা করব?
সাইদ রহমতলাহী

4
@ সাeedদ রাহমাতলাহী: হয় পদ্ধতিকে ব্যবহার করুন wait(যদি আপনার ব্লক করতে কোনও সমস্যা না হয়, অর্থাত্ যদি আপনি মূল থ্রেডে না থাকেন) বা একটি সম্পূর্ণ হ্যান্ডলার সরবরাহ করুন বা আপনার কলিং ক্লাসে বিজ্ঞপ্তি পদ্ধতির ব্যবহার করুন।
অগভীর চিন্তায়

কেন আপনি group.enterঅ্যাসিঙ্ক ব্লকের বাইরে কল করবেন ? গ্রুপে প্রবেশ করা এবং ছেড়ে দেওয়া কি প্রতিটি ব্লকের দায়িত্ব হওয়া উচিত নয়?
বিল

4
@ বিল waitঅবধি অপেক্ষা করে enterএবং leaveকলগুলি ভারসাম্যহীন। আপনি করা যদি enterঅবসান এ, waitঅপেক্ষা করতে না কারণ enterএখনো এবং এইভাবে সংখ্যা বলা হয় নি enterএবং leaveকল করা হয় সুষম (# == 0 লিখুন, # leav == 0)।
অগভীর চিন্তে

4
পরীক্ষাগুলির জন্য @ রুটিম্যাগনেট সম্ভবত এটি যাওয়ার উপায় নয়। ব্যবহারের XCTTestExpectationপরিবর্তে s। দেখুন এই নমুনা কোড
shallowThought

26

সুইফ্ট 3-এ, কোনও DispatchQueueকাজ শেষ করার পরে সমাপ্তি হ্যান্ডলারের কোনও প্রয়োজন নেই । তবুও আপনি বিভিন্নভাবে আপনার লক্ষ্য অর্জন করতে পারেন

একটি উপায় হ'ল:

    var a: Int?

    let queue = DispatchQueue(label: "com.app.queue")
    queue.sync {

        for  i in 0..<10 {

            print("Ⓜ️" , i)
            a = i
        }
    }

    print("After Queue \(a)")

লুপটি শেষ না হওয়া পর্যন্ত এটি অপেক্ষা করবে তবে এই ক্ষেত্রে আপনার মূল থ্রেডটি ব্লক হয়ে যাবে।

আপনি একই জিনিসটি এইভাবে করতে পারেন:

    let myGroup = DispatchGroup()
    myGroup.enter()
    //// Do your task

    myGroup.leave() //// When your task completes
     myGroup.notify(queue: DispatchQueue.main) {

        ////// do your remaining work
    }

একটি শেষ জিনিস: আপনি যদি ডিসপ্যাচকিউ ব্যবহার করে টাস্কটি সম্পূর্ণ করেন তবে আপনি যদি হ্যান্ডলারটি সম্পূর্ণ করতে চান তবে আপনি ব্যবহার করতে পারেন DispatchWorkItem

কীভাবে ব্যবহার করবেন তা এখানে একটি উদাহরণ DispatchWorkItem:

let workItem = DispatchWorkItem {
    // Do something
}

let queue = DispatchQueue.global()
queue.async {
    workItem.perform()
}
workItem.notify(queue: DispatchQueue.main) {
    // Here you can notify you Main thread
}

4
লুপের জন্য

2

প্রেরণ গ্রুপ ব্যবহার করুন

   dispatchGroup.enter()
   FirstOperation(completion: { _ in
dispatchGroup.leave()
  })
    dispatchGroup.enter()
    SecondOperation(completion: { _ in
dispatchGroup.leave()
  })
   dispatchGroup.wait() //Waits here on this thread until the two operations complete executing.

4
ধরে নিই যে আপনি এটিকে মূল কাতারে কল করেছেন, এটি অচলাবস্থার কারণ হবে।
অগভীর চিন্তে

নিবন্ধন করুন
Pretekro

আমি অন্য ক্লাসে একটি ফাংশন সম্পাদন করতে চাই তবে আমি সেই ফাংশনটি শেষ করার জন্য অপেক্ষা করতে চাই এবং তারপরে বর্তমান ক্লাসে কীভাবে এটি পরিচালনা করব?
সাইদ রহমতলাহী

4
যদিও উপরের উদাহরণটি মূল থ্রেডে অবরুদ্ধ হবে, পূর্ববর্তী উত্তরগুলি যেমন দেখিয়েছে, এর ভিতরে মোড়ানো DispatchQueue.global().async{}মূল সারিটি ব্লক করবে না।
জনিবি

2

সমাধানটির সুইফ্ট 5 সংস্করণ

func myCriticalFunction () value var value1: স্ট্রিং? var মান 2: স্ট্রিং?

let group = DispatchGroup()


group.enter()
//async operation 1
DispatchQueue.global(qos: .default).async { 
    // Network calls or some other async task
    value1 = //out of async task
    group.leave()
}


group.enter()
//async operation 2
DispatchQueue.global(qos: .default).async {
    // Network calls or some other async task
    value2 = //out of async task
    group.leave()
}


group.wait()

print("Value1 \(value1) , Value2 \(value2)") 

}


1

সুইফট 4

আপনি এই পরিস্থিতিতে অ্যাসিঙ্ক ফাংশন ব্যবহার করতে পারেন। আপনি যখন ব্যবহার করেন DispatchGroup(), কখনও কখনও অচলাবস্থার ঘটনা ঘটতে পারে।

var a: Int?
@objc func myFunction(completion:@escaping (Bool) -> () ) {

    DispatchQueue.main.async {
        let b: Int = 3
        a = b
        completion(true)
    }

}

override func viewDidLoad() {
    super.viewDidLoad()

    myFunction { (status) in
        if status {
            print(self.a!)
        }
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.