CFRunLoop非阻塞等待缓冲区被填充

时间:2012-04-27 16:12:53

标签: macos callback bluetooth wait runloop

我正在移植应用程序,将数据从BT设备读取到Mac。在特定于mac的代码中,我有一个类,其中包含BT回调的委托方法,如 - (void)rfcommChannelData:(...)

在该回调中,我用接收到的数据填充缓冲区。我有一个从应用程序调用的函数:

-(int) m_timedRead:(unsigned char*)buffer length:(unsigned long)numBytes time:(unsigned int)timeout
{

double steps=0.01;
double time = (double)timeout/1000;
bool ready = false;
int read,total=0;
unsigned long restBytes = numBytes;
while(!ready){
    unsigned char *ptr = buffer+total;
    read = [self m_readRFCOMM:(unsigned char*)ptr length:(unsigned long)restBytes];
    total+=read;
    if(total>=numBytes){
        ready=true; continue;
    }
    restBytes = numBytes-total;
    CFRunLoopRunInMode(kCFRunLoopDefaultMode, .4, false);       
    time -= steps;
    if(time<=0){
        ready=true; continue;
    }
}

我的问题是这个RunLoop让整个应用程序变得非常慢。如果我不使用默认模式,并使用runlooptimer创建我的runloop,则永远不会调用回调方法rfcommChannelData。我使用以下代码创建了一个runloop:

//  CFStringRef myCustomMode = CFSTR("MyCustomMode");
//  CFRunLoopTimerRef myTimer;
//  myTimer = CFRunLoopTimerCreate(NULL,CFAbsoluteTimeGetCurrent()+1.0,1.0,0,0,foo,NULL);   
//  CFRunLoopAddTimer(CFRunLoopGetCurrent(), myTimer, myCustomMode);
//  CFRunLoopTimerInvalidate(myTimer);
//  CFRelease(myTimer);

任何想法为什么默认的RunLoop会降低整个应用程序的速度,或者如何使我自己的运行循环允许来自rfcommchannel的回调被触发?

非常感谢,

Anton Albajes-Eizagirre

1 个答案:

答案 0 :(得分:1)

如果您正在使用GUI应用程序的主线程,请不要在内部运行自己的方法运行循环。安装运行循环源(或允许代表您的框架的异步API安装源)并返回主事件循环。也就是说,让执行流程退出代码并返回给调用者。主事件循环运行主线程的运行循环,当源准备就绪时,它们的回调将触发,这可能会调用你的方法。