代码之家  ›  专栏  ›  技术社区  ›  mahboudz

从后台任务调用-setneedsDisplay是否有问题?

  •  3
  • mahboudz  · 技术社区  · 15 年前

    我有一个更新视图的后台任务。该任务调用-setneedsDisplay以绘制视图。

    这工作:

    - (void) drawChangesTask;
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        if (pixels) {
            drawChanges((UInt32 *) origPixels, (UInt32 *) pixels, CGBitmapContextGetBytesPerRow(ctx)/4, CGBitmapContextGetHeight(ctx), count--);
    
            if (count < 0) {
                count = 150;
            }
            else
                [self performSelectorInBackground:@selector(drawChangesTask) withObject:nil ];
    
            [self performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO ];
    
        }
        [pool release];
    }
    

    这不起作用:

    - (void) drawChangesTask;
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        if (pixels) {
            drawChanges((UInt32 *) origPixels, (UInt32 *) pixels, CGBitmapContextGetBytesPerRow(ctx)/4, CGBitmapContextGetHeight(ctx), count--);
    
            if (count < 0) {
                count = 150;
            }
            else
                [self performSelectorInBackground:@selector(drawChangesTask) withObject:nil ];
    
            [self setNeedsDisplay];
    
        }
        [pool release];
    }
    

    有人知道为什么吗?当我说它不起作用的时候,我的意思是它运行了几十次迭代,有时我看到我的图像部分上下移动,或者完全空白,然后Deugger给了我一个 EXC_BAD_ACCESS 在核心图形的某个地方。

    另外,如果我自己不处理自动释放池,那么我会收到泄漏的错误消息。也不明白为什么会这样。我的drawChanges()不会创建任何新对象。错误如下:

    2009-08-17 11:41:42.358 BlurApp[23974:1b30f] *** _NSAutoreleaseNoPool(): Object 0xd78270 of class NSThread autoreleased with no pool in place - just leaking
    
    2 回复  |  直到 15 年前
        1
  •  8
  •   iKenndac    15 年前

    UIKit 简单地说,线程不安全,您需要调用在主线程上更新uikit控件的方法。

    我认为这一行:

    [self performSelectorInBackground:@selector(drawChangesTask) withObject:nil];
    

    正在引起麻烦。你试过在当前线程上再次调用它吗?如果需要在调用之间执行runloop,请使用:

    [self performSelector:@selector(drawChangesTask) withObject:nil afterDelay:0.0];
    

    这将在您所在的方法完成并且runloop循环一次之后,在当前线程上调用该方法。

        2
  •  2
  •   Daniel    15 年前

    这里的问题是,uikit不是线程安全的,如果你告诉你的用户界面从后台线程做一些事情,那么你要做的就是使用performselectornmainthread方法对你的用户界面元素进行更新。