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

时间:2019-11-27 13:45:32

标签: swift nsoperationqueue nsoperation

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

Command line: -opensource -confirm-license -release -prefix /Users/username/Desktop/dev/pv/paraview_build/install -I /Users/username/Desktop/dev/pv/paraview_build/install/include -L /Users/username/Desktop/dev/pv/paraview_build/install/lib -skip qtconnectivity -skip qtgamepad -skip qtlocation -skip qtmultimedia -skip qtsensors -skip qtserialport -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebsockets -nomake examples -nomake tests -no-dbus -qt-libjpeg -qt-pcre -system-zlib -no-openssl -skip qtsvg -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -qt-libpng
executing config test verifyspec
+ cd /Users/username/Desktop/dev/pv/paraview_build/superbuild/qt5/build/config.tests/verifyspec && /Users/username/Desktop/dev/pv/paraview_build/superbuild/qt5/build/qtbase/bin/qmake "CONFIG -= qt debug_and_release app_bundle lib_bundle" "CONFIG += shared warn_off console single_arch" 'QMAKE_LIBDIR += /Users/username/Desktop/dev/pv/paraview_build/install/lib' 'INCLUDEPATH += /Users/username/Desktop/dev/pv/paraview_build/install/include' /Users/username/Desktop/dev/pv/paraview_build/superbuild/qt5/src/qtbase/config.tests/verifyspec
> Project ERROR: QMAKE_MAC_SDK can only contain short-form SDK names (eg. macosx, iphoneos)

后来我有了:

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()的属性设置为true。但是当我在完成的处理程序中检查它时,它是错误的。我想这是预期的行为。但是检查我的操作是否被取消的正确方法是什么?

这是我的操作课:

isCancelled

1 个答案:

答案 0 :(得分:1)

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

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

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

您后来说:

  

我看到isCancelled完成后调用了completionHandler

是的,是的。

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

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