【问题标题】:Is it possible to kill long running task during it execution?是否可以在执行期间杀死长时间运行的任务?
【发布时间】:2017-09-20 11:14:25
【问题描述】:

我有一个预构建的 C 库(二进制文件和头文件),其中包含一个重功能。此功能可能需要几分钟或更长时间才能完成。通常我使用 GCD 在后台移动计算并保持 UI 线程空闲:

// show activity indicator or something else

dispatch_queue_t queue = dispatch_queue_create(NULL, NULL);
dispatch_async(queue, ^{
    void *resultData = callOfHeavyLibraryMethodHere(params);
    dispatch_async(dispatch_get_main_queue(), ^{
        // show resultData to user
    });
});

但是如果用户想取消这个操作呢?据我所知,我无法停止 GCD 的运行块。我读到了NSThread - 但它也无法从另一个线程(主线程)中杀死一个线程(通过计算)。还有其他解决方案吗?

我不能使用这个答案How to cancel/exit/stop execution of Thread object or thread running in background in IOS 的解决方案,因为即使我调用cancel 方法我也没有地方检查isCancelled 变量。

这不是我的情况:

NSOperationQueue* myQueue = [[NSOperationQueue alloc] init];
NSBlockOperation* myOp = [[NSBlockOperation alloc] init];

[myOp addExecutionBlock:^{
    for (int i = 0; i < 1000000; i++)
    {
        if ([myOp isCancelled]) // <-- check and interrupt operation
            return;
        doSmallPartOfWorkForItemAtIndex(i);
    }
}];
[myQueue addOperation:myOp];

这是我的情况:

NSOperationQueue* myQueue = [[NSOperationQueue alloc] init];
NSBlockOperation* myOp = [[NSBlockOperation alloc] init];

[myOp addExecutionBlock:^{
    void *resultData = callOfHeavyLibraryMethodHere(params);
    // pass data somewhere else
}];
[myQueue addOperation:myOp];

没有办法检查isCancelled,操作不会以这种方式中断。我也不能调用[NSThread exit],因为我的代码中没有中间点。

【问题讨论】:

标签: ios asynchronous grand-central-dispatch nsthread cancellation


【解决方案1】:

调度队列的问题是,一旦你调度了一个任务,你就不能取消它。但是,您可以改用NSOperationQueue

NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    void *resultData = callOfHeavyLibraryMethodHere(params);
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        // Main thread work (UI usually)
    }];
}];

NSOperationQueue *queue = [NSOperationQueue new];
[queue addOperation:operation];
// you can cancel an operation like so
[operation cancel];

取消任务的能力是NSOperationQueue 相对于 GCD 的优势之一。另一个是可以在操作之间添加依赖关系,这真的很方便。

【讨论】:

  • 对不起,但据我了解,在这种情况下,我的 NSOperation(或其子类)必须支持取消,但由于我的库限制,我无法提供小块和 isCancelled 变量观察(一项艰巨的任务,没有部分)。 stackoverflow.com/questions/7820960/…
  • 您不需要提供小块或监控任何东西 - 只需将所有代码放入 NSBlockOperation 并将其添加到 NSOperationQueue。而且,如果您需要取消,只需致电cancel 进行操作即可。
  • 但在这里:stackoverflow.com/a/13030641/7886687 我也看到 isCancelled 属性检查。好的,我将在我的案例中测试这个解决方案并写下结果。
  • 是的,在您引用的答案中,有isCanceled 属性检查。 需要定期检查吗?
  • 所以,正如我所料,“取消”方法调用什么也不做。任务永不停止。这是因为您必须检查 isCancelled 并中断您的代码。但这只有在某个循环中有大量数据时才有可能。在我的代码中没有循环。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多