dop*_*ime 5 macos cocoa multithreading objective-c nsview
在我的代码中,我进行了子类化,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.
}
Run Code Online (Sandbox Code Playgroud)
当我从Xcode运行相同的程序时,它运行正常.输出如下所示.

但是当我从外面运行它时,有问题,输出如下所示.

首先,我想知道从二级线程中绘制是否正确?或者从辅助线程中提取的另一种方法是什么?
这个问题背后的原因是什么?
Ken Aspeslagh对于从辅助线程中绘制有些不正确(他是正确的,这通常是一个坏主意).从我所看到的代码中你没有一个很好的用例来绘制辅助线程.你能解释一下你为什么要这样做吗?
你自己已经发现了setCanDrawConcurrently:哪个明确地讨论了drawRect:从后台线程调用.请注意,视图窗口必须allowsConcurrentViewDrawing设置为YES才能使其生效(这是默认设置).
苹果自己的Cocoa绘图指南中有一个关于从辅助线程绘制的部分.我已经强调了一些我认为与你相关的部分.
Application Kit为每个窗口和线程组合维护一个独特的图形上下文.因为每个线程都有自己的给定窗口的图形上下文对象,所以可以使用辅助线程绘制到该窗口.但是,有一些警告.
在Windows的正常更新周期中,所有绘图请求都将发送到应用程序的主线程进行处理.当用户事件触发用户界面的更改时,会发生正常的更新周期.在这种情况下,您可以从应用程序的主线程调用setNeedsDisplay:或setNeedsDisplayInRect:方法(或显示系列方法),以使视图中需要重绘的部分无效.您不应该从任何辅助线程调用这些方法.
如果要从辅助线程更新窗口或视图,则必须手动将焦点锁定在窗口或视图上并自行启动绘图.锁定焦点为该窗口的图形上下文配置绘图环境.锁定后,您可以配置绘图环境,照常发出绘图命令,然后将图形上下文的内容刷新到窗口缓冲区.
为了在辅助线程上定期绘制,您必须自己通知线程.发送常规通知的最简单方法是使用NSTimer或NSAnimation对象.有关如何为内容设置动画的详细信息,请参阅"高级绘图技术".
Cocoa线程编程指南也说:
如果要使用线程绘制视图,请在NSView的lockFocusIfCanDraw和unlockFocus方法之间括起所有绘图代码
除此之外,GCD块调用可能是一种更好的方法,用于在后台执行小组操作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];
});
Run Code Online (Sandbox Code Playgroud)
但是,这可能与您的问题无关; 我之所以提到它只是因为我认为它会更好地为你提供GCD队列.