如何检查操作是否被取消?

问题描述 投票:0回答:1

我想知道我的操作是否被取消或正常完成。这是我的代码片段:

class PacketReceiver {
    private let m_executer = OperationQueue()
    private var m_operation : Operation?

    private func operationFinishedHandler()
    {
        if let op = m_operation {
            if op.isCancelled {
                print("Operation cancelled")
            } else {
                print("Operation finished OK \(op.isCancelled)")
            }
        }
    }

    func start()
    {
        let rxPacketOperation = PacketReceiverOperation()
        rxPacketOperation.completionBlock = self.operationFinishedHandler
        m_operation = rxPacketOperation

        m_executer.addOperation(rxPacketOperation)
    }

    func cancel()
    {
        if let op = m_operation {
            op.cancel()
        }
    }

    func join()
    {
        if let op = m_operation {
            print("is op cancelled = \(op.isCancelled)")
        }

        m_executer.waitUntilAllOperationsAreFinished()

        if let op = m_operation {
            print("is op cancelled = \(op.isCancelled)")
        }
    }
}

后来我有:

let packetReceiver = PacketReceiver()
packetReceiver.start()

packetReceiver.cancel()
packetReceiver.join()

[我看到join()方法isCancelled内部的属性设置为true。但是当我在完成的处理程序中检查它时,它是错误的。我想这是预期的行为。但是检查我的操作是否被取消的正确方法是什么?

这是我的操作课:

class PacketReceiverOperation : Operation {
    private var m_packetData : String = ""
    private let m_simDataProvider = SimDataProvider(okAttemptId : 2)
    private let m_currentTimeProvider = CurrentTimeProvider()

    private func prepareReceiver() {
        m_packetData = ""
        print("\(m_currentTimeProvider.getCurrentTimeAsString()) : prepare SIM receiver")
    }

    override func main() {
        if isCancelled {
            return
        }

        prepareReceiver()

        if isCancelled {
            return
        }

        var isPacketReceived = false
        var isFirstChunkReceived = false

        repeat {
            if isCancelled {
                return
            }

            if let chunkData = m_simDataProvider.getPacket() {
                isFirstChunkReceived = true
                m_packetData.append(";" + chunkData)
            } else {
                if isFirstChunkReceived {
                    isPacketReceived = true
                }
            }
        } while isPacketReceived == false
    }
}
swift nsoperationqueue nsoperation
1个回答
1
投票

[由于多种原因(尤其是缺少抢先取消和一般比赛条件),isCancelled状态不是一种可靠的方式来知道您的Operation子类是否成功完成。 (它告诉您是否尝试取消,但基本任务是否成功。)

由于这个原因,我很少使用内置的completionHandler(没有参数),而是通常实现自己的自定义完成处理程序闭包,该闭包提供Result(或其他任何东西)作为参数。这消除了所有歧义。

或者,在您的情况下,您可以将isPacketReceived设置为操作的属性,而不是局部变量,然后您可以查看该值以确定是否完全接收到数据包,而不是isCancelled。] >

您稍后说:

[我看到completionHandler完成后调用了join()

是的,是的。

但是,join根本就是一个同步方法,这有点令人担忧(即,您正在调用waitUntilAllOperationsAreFinished)。操作队列的目的是让我们可以为可能耗时的任务采用异步模式,并将其从主线程中删除。在我们等待操作完成时阻塞(特别是如果您从主线程调用join时)似乎无法达到目的。

我鼓励您采用异步模式,只需将您的操作添加到队列中,然后在其完成处理程序中启动所需的任何内容(无论是默认的还是您自己的)。

© www.soinside.com 2019 - 2024. All rights reserved.