如何派遣code块在iOS上的同一个线程? [英] How to dispatch code blocks to the same thread in iOS?

查看:228
本文介绍了如何派遣code块在iOS上的同一个线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题的主要方面:这是关于iOS的。可在某种程度上,我莫名其妙地派遣code块,他们将所有(一)背景及(b)在同一个线程上运行?我想在后台运行一些耗时的操作,但这些都必须在同一线程上运行,因为它们涉及的资源,也不得线程之间共享。

Main aspect of the question: It's about iOS. Can I somehow dispatch code blocks in a way, that they will all (a) run in background and (b) on the same thread? I want to run some time-consuming operations in background, but these have to be run on the same thread, because they involve resources, that mustn't be shared among threads.

进一步的技术细节,如果需要的话:这是关于实施的Apache科尔多瓦,为移动平台HTML5应用框架一个SQLite插件。这个插件应该是的WebSQL 在科尔多瓦的插件API的方式实现。 (这意味着,这是不可能的单块中包裹整个交易,有什么可以让一切更简单。)

Further technical details, if required: It's about implementing an sqlite plugin for Apache Cordova, a framework for HTML5 apps on mobile platforms. This plugin should be an implementation of WebSQL in the means of the Cordova's plugin API. (That means, it's not possible to wrap entire transactions within single blocks, what could make everything easier.)

下面是从科尔多瓦的Docs一些code:

Here is some code from Cordova's Docs:

- (void)myPluginMethod:(CDVInvokedUrlCommand*)command
{
    // Check command.arguments here.
    [self.commandDelegate runInBackground:^{
        NSString* payload = nil;
        // Some blocking logic...
        CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:payload];
        // The sendPluginResult method is thread-safe.
        [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
    }];
}

但据我所知,没有任何保证,那些派遣code块(见 runInBackground )将在同一个线程上运行。

But as far as I know, there is no guarantee, that those dispatched code blocks (see runInBackground) will run on the same thread.

推荐答案

GCD不保证两个街区在同一线程上运行,即使它们属于同一个队列(与主队列之外,当然) 。然而,如果您使用的是串行队列( DISPATCH_QUEUE_SERIAL ),这不是一个问题,因为你后来才知道有你的数据没有并发访问。

GCD makes no guarantee that two blocks run on the same thread, even if they belong to the same queue (with the exception of the main queue, of course). However, if you're using a serial queue (DISPATCH_QUEUE_SERIAL) this isn't a problem as you then know that there is no concurrent access to your data.

该名男子页 dispatch_queue_create 说:

队列不一定要执行,并提交给独立的队列块的任何特定的线程可以并发执行。

Queues are not bound to any specific thread of execution and blocks submitted to independent queues may execute concurrently.

我不知道任何方式到队列绑定到特定的线程(毕竟,不需要去在意线程是GCD的一个重要点)。 为什么你可以使用一个串行队列,而不必担心实际的线程原因是这样的承诺:

I'm not aware of any way to bind a queue to a specific thread (after all, not needing to care about threads is a major point of GCD). The reason why you can use a serial queue without worrying about the actual thread is this promise:

所有的内存写入由派遣到一个串行队列块执行都保证是分派到同一个队列后续块可见。

All memory writes performed by a block dispatched to a serial queue are guaranteed to be visible to subsequent blocks dispatched to the same queue.

也就是说,存储器屏障似乎被使用。

That is, a memory barrier seems to be used.

当线程问题处理,您主要关注的通常是避免两个线程同时访问的东西。如果您使用的是串行的队列你没有这个问题。它通常并不重要的线程访问你的资源。例如,我们正在使用的串行队列管理没有问题的核心数据访问。

When dealing with threading issues, your main concern is usually to avoid that two threads access something concurrently. If you're using a serial queue you do not have this problem. It usually doesn't really matter which thread is accessing your resources. For example, we're using serial queues to manage Core Data access without a problem.

编辑:

看来你真的发现了,你必须工作在同一线程上难得一遇。你可以实现你自己的工作线程:

It seems you really found a rare case where you need to be working on the same thread. You could implement your own worker thread:


  • prerequisites:

    • 系统的NSMutableArray(姑且称之为 blockQueue )。

    • 系统NSCondition(姑且称之为 queueCondition )。

    • Prerequisites:
      • A NSMutableArray (let's call it blockQueue).
      • A NSCondition (let's call it queueCondition).

      • 线程的方法有一个无限循环中,它锁定的情况下,等待它,如果队列为空(与跳槽布尔是假的),取出一个块,并执行它。

      由于条件,该线程将简单的睡觉,而没有工作可做。

      Due to the condition, the thread will simply sleep while there's no work to do.

      所以,大致(未经测试,假设ARC):

      So, roughly (untested, assuming ARC):

      - (void)startWorkerThread
      {
          workerThread = [[NSThread alloc]
              initWithTarget:self
              selector:@selector(threadMain)
              object:nil
          ];
          [workerThread start];
      }
      
      - (void)threadMain
      {
          void (^block)();
          NSThread *currentThread;
      
          currentThread = [NSThread currentThread];
      
          while (1) {
              [queueCondition lock];
              {
                  while ([blockQueue count] == 0 && ![currentThread isCancelled]) {
                      [queueCondition wait];
                  }
      
                  if ([currentThread isCancelled]) {
                      [queueCondition unlock];
                      return;
                  }
      
                  block = [blockQueue objectAtIndex:0];
                  [blockQueue removeObjectAtIndex:0];
              }
              [queueCondition unlock];
      
              // Execute block outside the condition, since it's also a lock!
              // We want to give other threads the possibility to enqueue
              // a new block while we're executing a block.
              block();
          }
      }
      
      - (void)enqueue:(void(^)())block
      {
          [queueCondition lock];
          {
              // Copy the block! IIRC you'll get strange things or
              // even crashes if you don't.
              [blockQueue addObject:[block copy]];
              [queueCondition signal];
          }
          [queueCondition unlock];
      }
      
      - (void)stopThread
      {
          [queueCondition lock];
          {
              [workerThread cancel];
              [queueCondition signal];
          }
          [queueCondition unlock];
      }
      

      这篇关于如何派遣code块在iOS上的同一个线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆