title: How can I use CoreBluetooth for Python without giving up the main thread
body: <p>I am trying to implement a generic BLE interface that will run on OS/X and talk to a BLE peripheral device. The peripheral is very complex: It can be queried, sent hundreds of different commands, offers notifications, etc. I need to be able to connect to it, send it commands, read responses, get updates, etc.</p>
  
  <p>I have all of the code I need but am being frustrated by one thing: From the limited information I can find online, it looks like the only way to make CoreBluetooth's delegate callbacks get called is by running:</p>
  
  <pre><code>from PyObjCTools import AppHelper
  
  # [functional CoreBluetooth code that scans for peripherals]
  AppHelper.runConsoleEventLoop()
  </code></pre>
  
  <p>The problem is that <code>AppHelper.runConsoleEventLoop</code> blocks the main thread from continuing, so I cannot execute code to interact with the peripheral.</p>
  
  <p>I have tried running the event loop:</p>
  
  <ul>
  <li>From a different thread ---> Delegate callbacks not called</li>
  <li>From a subprocess ---> Delegate callbacks not called</li>
  <li>From a forked child ---> Python crashes with error message: <code>The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec().</code></li>
  <li>From <code>multiprocessing.Pool(1).apply_async(f)</code> ---> Python crashes with error message: <code>The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec().</code></li>
  </ul>
  
  <p>all without success.</p>
  
  <p>I do not understand the nature of <code>AppHelper.runConsoleEventLoop</code>. Why does it need to be run in order for the CoreBluetooth delegate callbacks to be called? Is there some other version that can be called that doesn't have to be run on the main thread? I read something on the web about it being GUI related and therefore had to be run on the main thread but my python application does not have any GUI elements. Is there a flag or API that is less concerned with GUI that I could use?</p>
  
  <p>Any help would be enormously appreciated. Thanks for your time!</p>
  
  <p><strong>Update:</strong></p>
  
  <p>I spoke with an iOS/CoreBluetooth expert at work and found out that Dispatch Queues are probably the solution. I dug further and found that the author of the PyObjC package recently released a v4.1 that adds support for dispatch queues that was heretofore missing.</p>
  
  <p>I've been reading Apple developer documentation for hours now and I understand that it's possible to create Dispatch Source objects that monitor certain system events (such as BLE peripheral events that I am interested in) and that configuring them involves creating and assigning a Dispatch Queue, which is the class that calls my CBCentralManager delegate callback methods. The one piece of the puzzle that I am still missing is how to connect the Dispatch Source/Queue stuff to the <code>AppHelper.runConsoleEventLoop</code>, which calls <code>Foundation.NSRunLoop.currentRunLoop()</code>. If I put the call to <code>AppHelper</code> on a separate thread, how do I tell it which Dispatch Source/Queue to work with in order to get event info?</p>