我在iOS上的CoreMIDI连接显然足够快,可以处理任何打击它的事情……如果我只是在做一些简单的对象创建和NSLog的话。在用户界面中,我没有时间处理其中的所有内容。用户界面会崩溃,或者太晚才完成处理。

但是,我需要对CoreMIDI输入做出真实的处理和UI显示。我想要的是每隔1毫秒或2毫秒处理一次最新消息。我一直使用一个收集器来执行此操作,该收集器每隔1ms(processFromServerAsync)被计时器触发的方法清空。一个问题是,如果我抓住并替代以下内容,我认为某些消息可能会掉入裂缝:

NSDictionary *queueCopy = [self.queue copy];
// here the dictionary could get messages not in the queue copy!
self.queue = [NSMutableDictionary dictionary];


我意识到我可以通过与锁同步来处理此问题,这很容易搞砸:

-(NSMutableDictionary *)messageQueue {
    @synchronized(self) {
        if (!messageQueue_)
            self.messageQueue = [NSMutableDictionary dictionary];
        return messageQueue_;
    }
}

-(NSDictionary*)clearMessageQueueAndReturnCopy {
    @synchronized(self) {
        if (!messageQueue_)
            return [NSDictionary dictionary];
        NSDictionary *retVal = [messageQueue_ copy];
        self.messageQueue = [NSMutableDictionary dictionary];
        return retVal;
    }
}


但是,我不相信自己甚至会以正确的方式进行处理。通常如何进行节流(即使在Obj-C之外)?我当然不能在UI或程序中处理所有这些消息。

最佳答案

有一些完善的模式可用于限制传入数据流。这在财务方面起了很大的作用,您可能有一个数据提要,该数据提要在系统上每秒发送10万条消息。

您使用滑动窗口机制来丢弃冗余消息,同时确保客户端具有最新的数据副本。您在某个时间段(几毫秒)内设置了窗口,然后为每个数据流(意味着特定的CC,MIDI音符等)设置了队列。当第一条消息进入时,您将启动全局计时器。您发送该消息立即给客户。如果在窗口期间出现其他任何情况,则将其推入队列。队列只有一个条目-最新值-因此,每次后续更新都会覆盖队列中的值。当计时器计时(窗口结束)时,您会将最新消息发送给客户端。然后,您会在收到下一条消息后立即将其发送出去,打开一个新窗口并重复执行。这在使客户端陷入沼泽和避免将更新间隔混叠到计时器窗口之间达到了合理的平衡。别名间隔为1-2ms的问题较少,因此较粗糙的刚性计时器方法可能对您有用。

关键是要确保每个数据流都有单独的窗口。您不能冒险改写或忽略注释,因为有控件更改进来了。一个计时器,每个Midi消息号一个单入队列。

关于ios - 如何在Objective-C中限制CoreMIDI,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/8524765/

10-11 19:56