3

NSViewをレンダリングし、他の場所で使用するための画像としてHTTPインターフェイスを介して返すMacOSXサーバーアプリケーションがあります。表示されるUIはなく、アプリケーションはNSWindowなしでデタッチされたNSViewを作成します。

アプリケーションは一度に多くのリクエストを受信できますが、Cocoa UIはスレッドセーフではないため、レイアウトとレンダリングのプロセスはメインスレッドを中心に同期されます(GCDのdispatch_syncを使用)。コード。

各リクエストが完全に分離されており、それらの間で何も共有されていないことを考えると、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 に答える