首页 文章

Cocoa中的多个UI线程

提问于
浏览
2

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

应用程序可以同时接收许多请求,但是布局和呈现过程围绕主线程同步(使用GCD中的dispatch_sync),因为Cocoa UI不是线程安全的,在一部分时间内将吞吐量减少到单个请求代码 .

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

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

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;
                });
            });
        }
    }
    

    这里的关键是一切都是背景渲染任务的“私有” . 它有自己的视图,自己的图形上下文等 . 如果你没有分享任何东西,这应该没问题 . 既然你明确地说过,“鉴于每个请求完全是分开的,它们之间没有任何共享”,我怀疑你已经满足了这个条件 .

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

相关问题