3

我有一个 Mac OS X 服务器应用程序,它呈现 NSViews 并通过 HTTP 接口将它们作为图像返回以供其他地方使用。没有可见的 UI,应用程序创建了没有 NSWindow 的分离的 NSView。

应用程序可以一次接收多个请求,但布局和渲染过程围绕主线程同步(使用 GCD 中的 dispatch_sync),因为 Cocoa UI 不是线程安全的,在该部分中将吞吐量降低到一次单个请求编码。

鉴于每个请求都是完全独立的,它们之间没有共享任何内容,Cocoa 应用程序有没有办法有效地运行多个完全独立的 UI 线程?也许使用多个运行循环?

如果可能的话,我想避免运行多个进程。

4

1 回答 1

1

很难肯定地说这将满足​​您的特定需求(因为您的特定需求可能具有未在您的问题中提到的主线程依赖项),但我在这里没有看到任何特别有争议的东西。例如,以下代码可以正常工作而不会发生意外:

CGImageRef CreateImageFromView(NSView* view)
{
    const CGSize contextSize = CGSizeMake(ceil(view.frame.size.width), ceil(view.frame.size.height));
    const size_t width = contextSize.width;
    const size_t height = contextSize.height;
    const size_t bytesPerPixel = 32;
    const size_t bitmapBytesPerRow = 64 * ((width * bytesPerPixel + 63) / 64 ); // Alignment
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, bitmapBytesPerRow, colorSpace, kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedLast);
    CGColorSpaceRelease(colorSpace);
    [view displayRectIgnoringOpacity: view.bounds inContext: [NSGraphicsContext graphicsContextWithGraphicsPort: context flipped: YES]];
    CGImageRef image = CGBitmapContextCreateImage(context);
    CGContextRelease(context);
    return image;
}

- (IBAction)doStuff:(id)sender
{
    static NSUInteger count = 0;

    for (NSUInteger i =0; i < 100; ++i)
    {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSButton* button = [[[NSButton alloc] initWithFrame: NSMakeRect(0, 0, 200, 100)] autorelease];
            button.title = [NSString stringWithFormat: @"Done Stuff %lu Times", (unsigned long)count++];
            CGImageRef image = CreateImageFromView(button);
            NSImage* nsImage = [[[NSImage alloc] initWithCGImage:image size: NSMakeSize(CGImageGetWidth(image), CGImageGetHeight(image))] autorelease];
            CGImageRelease(image);
            dispatch_async(dispatch_get_main_queue(), ^{
                self.imageView.image = nsImage;
            });
        });
    }
}

这里的关键是一切都是后台渲染任务的“私有”。它有自己的视图、自己的图形上下文等。如果您不共享任何内容,这应该没问题。既然您明确表示,“鉴于每个请求都是完全独立的,它们之间没有共享任何内容”,我怀疑您已经满足了这个条件。

试试看。如果您遇到麻烦,请发表评论。

于 2013-02-11T14:32:05.117 回答