gpt4 book ai didi

objective-c - 多线程在 NSView 中绘制

转载 作者:太空狗 更新时间:2023-10-30 03:48:56 26 4
gpt4 key购买 nike

在我的代码中,我将 NSView 子类化,并在其 drawRect 方法中生成三个线程来执行绘图。

-(void)drawRect:(NSRect)dirtyRect
{
[[self window] setAllowsConcurrentViewDrawing:YES];
[self setCanDrawConcurrently:YES];

[NSThread detachNewThreadSelector:@selector(DrawText) toTarget:self withObject:nil];
[NSThread detachNewThreadSelector:@selector(DrawRectangle) toTarget:self withObject:nil];
[NSThread detachNewThreadSelector:@selector(DrawGradient) toTarget:self withObject:nil];

//Wherease these functions DrawText, DrawRectangle and DrawGradient performs their task as suggested by name.

//In DrawText, DrawRectangle, and DrawGradient lockFocus and unlockFocus is being
// used for multithreaded drawing.

}

当我从 Xcode 运行相同的程序时,它运行良好。输出如下所示。 Single threaded

但是当我从外部运行它时,出现了问题,输出如下所示。 Multithreaded

首先,我想知道从辅助线程中绘制是否正确?或者从辅助线程中提取的另一种方法是什么?

这个问题背后的原因是什么?

最佳答案

Ken Aspeslagh 关于从辅助线程绘制的说法有些不正确(他是正确的,这通常是个坏主意)。从我看到的你的代码来看,你没有一个很好的用例来绘制辅助线程。您能解释一下为什么要这样做吗?

您自己已经发现了 setCanDrawConcurrently:,它明确谈到了从后台线程调用 drawRect:。请注意, View 窗口必须将 allowsConcurrentViewDrawing 设置为 YES 才能正常工作(这是默认设置)。

苹果拥有 Cocoa Drawing Guide有一个关于从辅助线程绘制的部分。我突出显示了一些我认为与您相关的部分。

The Application Kit maintains a unique graphics context for each window and thread combination. Because each thread has its own graphics context object for a given window, it is possible to use secondary threads to draw to that window. There are some caveats, however.

During the normal update cycle for windows, all drawing requests are sent to your application’s main thread for processing. The normal update cycle happens when a user event triggers a change in your user interface. In this situation, you would call the setNeedsDisplay: or setNeedsDisplayInRect: method (or the display family of methods) from your application’s main thread to invalidate the portions of your view that require redrawing. You should not call these methods from any secondary threads.

If you want to update a window or view from a secondary thread, you must manually lock focus on the window or view and initiate drawing yourself. Locking focus configures the drawing environment for that window's graphics context. Once locked, you can configure the drawing environment, issue your drawing commands as usual, and then flush the contents of the graphics context to the window buffer.

In order to draw regularly on a secondary thread, you must notify the thread yourself. The simplest way to send regular notifications is using an NSTimer or NSAnimation object. For more information on how to animate content, see “Advanced Drawing Techniques.”

The Cocoa Threading Programming Guide还说:

If you want to use a thread to draw to a view, bracket all drawing code between the lockFocusIfCanDraw and unlockFocus methods of NSView

顺便说一句,GCD block 调用可能是一种比 NSThread 更好的在后台执行小型操作集的方法。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// you can put each of these calls in their own queue if you want
[self DrawText];
[self DrawRectangle];
[self DrawGradient];
});

但是,这可能与您的问题无关;我提到它只是因为我认为使用 GCD 队列会更好地为您服务。

关于objective-c - 多线程在 NSView 中绘制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19954424/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com