paint-brush
OperationQueue + Asenkron Kod: Bilmeniz Gereken Her Şeyile@bugorbn
528 okumalar
528 okumalar

OperationQueue + Asenkron Kod: Bilmeniz Gereken Her Şey

ile Boris Bugor5m2024/03/17
Read on Terminal Reader

Çok uzun; Okumak

Swift'de eşzamanlı kod için bir işlem kuyruğu kullanmak tam bir cehennem gibi görünebilir çünkü aslında kodlarının derlenmesi tamamlanırsa kodun tamamlanmış olduğu kabul edilir. Eşzamansız kod yürütüldüğünde "İşlem"in kendisi zaten tamamlanmış olacaktır. Sorunun nasıl çözüleceğini anlamak için operasyonun yaşam döngüsünün nasıl çalıştığını anlamanız gerekir.
featured image - OperationQueue + Asenkron Kod: Bilmeniz Gereken Her Şey
Boris Bugor HackerNoon profile picture

Swift'de, eşzamansız kod için OperationQueue kullanmak tam bir cehennem gibi görünebilir çünkü aslında, eşzamanlı kodlarının derlenmesi tamamlanırsa Operations tamamlanmış kabul edilir.


Başka bir deyişle, aşağıda açıklanan örneğin derlenmesi bozuk bir yürütme emri verecektir çünkü asenkron kod yürütüldüğünde Operation kendisi zaten tamamlanmış olacaktır.


 let operationQueue = OperationQueue() operationQueue.maxConcurrentOperationCount = 1 operationQueue.addOperation { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { print("First async operation complete") } print("First sync operation complete") } operationQueue.addOperation { DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { print("Second async operation complete") } print("Second sync operation complete") }


Bu kod yazdırılacaktır:


 First sync operation complete Second sync operation complete First async operation complete Second async operation complete


Ancak bu kısıtlamaları aşmanın bir yolu var. Sorunun nasıl çözüleceğini anlamak için Operation arka planda nasıl çalıştığını anlamanız gerekir.


Operation kendisinde, operasyonun yaşam döngüsünü takip edebileceğiniz dört bayrak bulunur:


  • isReadyOperation şu anda gerçekleştirilip gerçekleştirilemeyeceğini gösterir.


  • isExecuting —bir Operation şu anda devam edip etmediğini gösterir.


  • isFinished Operation şu anda tamamlanıp tamamlanmadığını gösterir.


  • isCancelled Operation iptal edilip edilmediğini gösterir.


Teorik olarak, Operation Operation eşzamansız olarak yürütülmeden önce isFinished durumuna girer, bu nedenle, Operation yaşam döngüsünü yönetebileceğimiz bir teknik geliştirmemiz gerekir.


Bu olasılık, Operation alt sınıflara ayırarak ve ayrıca start / cancel yöntemlerinin yanı sıra operasyonun yaşam döngüsünün oluşturulduğu tüm bayrakların yeniden tanımlanmasıyla çözülebilir.


İşte kod:


 public class AsyncOperation: Operation { // MARK: Open override open var isAsynchronous: Bool { true } override open var isReady: Bool { super.isReady && self.state == .ready } override open var isExecuting: Bool { self.state == .executing } override open var isFinished: Bool { self.state == .finished } override open func start() { if isCancelled { state = .finished return } main() state = .executing } override open func cancel() { super.cancel() state = .finished } // MARK: Public public enum State: String { case ready case executing case finished // MARK: Fileprivate fileprivate var keyPath: String { "is" + rawValue.capitalized } } public var state = State.ready { willSet { willChangeValue(forKey: newValue.keyPath) willChangeValue(forKey: state.keyPath) } didSet { didChangeValue(forKey: oldValue.keyPath) didChangeValue(forKey: state.keyPath) } } }


Operation aldığımız alt sınıf temeldir ve manuel olarak zorla tamamlamamıza olanak tanır.


Tamamlama bloklarıyla çalışmak için başka bir alt sınıf oluşturmalısınız. Ancak bu, Operation değil AsyncOperation öğesinin bir alt sınıfı olacaktır.


 public typealias VoidClosure = () -> Void public typealias Closure<T> = (T) -> Void public class CompletionOperation: AsyncOperation { // MARK: Lifecycle public init(completeBlock: Closure<VoidClosure?>?) { self.completeBlock = completeBlock } // MARK: Public override public func main() { DispatchQueue.main.async { [weak self] in self?.completeBlock? { DispatchQueue.main.async { self?.state = .finished } } } } // MARK: Private private let completeBlock: Closure<VoidClosure?>? }


Bu alt sınıf, Operation bir kapanış geçirmemize izin verecek ve ardından Operation tamamlanacak.


Bu tür bir işlemi pratikte deneyelim:


 let operationQueue = OperationQueue() operationQueue.maxConcurrentOperationCount = 1 operationQueue.addOperation( CompletionOperation { completion in DispatchQueue.main.asyncAfter(deadline: .now() + 1) { print("First async operation complete") completion?() } print("First sync operation complete") } ) operationQueue.addOperation( CompletionOperation { completion in DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { print("Second async operation complete") completion?() } print("Second sync operation complete") } )


Sonuç olarak, Operations eşzamanlı yürütülmesini sağlamayı başardık:


 First sync operation complete First async operation complete Second sync operation complete Second async operation complete


Benimle iletişime geçmekten çekinmeyin heyecan Eğer sorunuz varsa. Ayrıca her zaman yapabilirsiniz bana bir kahve al .


Burada da yayınlandı