2011-09-30 47 views
2

我有一个线程正在递增变量“int count”的值。我想用新的“int count”值更新我的UI,直到我按停止按钮停止增量。我已经设法更新用户界面,但内存占用不断增长。它不会显示为内存泄漏,但它是一个分配问题。每次调用线程中的UI元素时,堆大小都会增加。我可以清楚地看到仪器泄漏分配部分,我有一些分配只有在移动触摸UI元素的窗口时才会被释放。尽管尝试了一切,我仍然无法解决问题。 如果有更好的方法用“int count”新值更新UI元素,请随时通知我。 谢谢objective c cocoa从单独的线程更新gui

我发布了下面的可可项目的链接,如果你想运行仪器或分配来查看问题或查看源代码。这是一个只有几行的小型项目。所有的

Xcode Poject GUI UPDATE LINK

-(void) incrementCountGUI:(id)param{ // increment count and update gui 
    NSAutoreleasePool *pool=[[NSAutoreleasePool alloc]init];// pool just added 

    count++; 
    if (count>=100) {// MAKE SURE COUNT DOESN'T GO ABOVE 100 
     count=0; 
    } 
    [sliderDisplayOutlet setIntValue:count];// display value of count in textfield 
    [sliderOutlet setIntValue:count];// move slider to value of count 

    [pool release]; 
} 


+(void) updateSliderThread:(id)param{// this thread will call incrementCountGUI method to continuously upgrade UI in the background 

    NSAutoreleasePool *myThreadPool=[[NSAutoreleasePool alloc]init]; 
while (shoudStop==NO) { 
    [ sharedAppInstance performSelectorOnMainThread:@selector(incrementCountGUI:) // update ui in main thread 
             withObject:nil 
             waitUntilDone:NO]; 
    usleep(5000);// sleep microsec; 
} 
    [myThreadPool release]; 
} 

- (IBAction)stopCountAction:(id)sender {// START OR STOP counter thread 

    if ([stopCountButtonOutlet state]==1) { // button depressed=>START 
     shoudStop=NO; 
     [NSThread detachNewThreadSelector:@selector(updateSliderThread:) toTarget:[AppController class] withObject:nil]; 
     [stopCountButtonOutlet setTitle: @" STOP" ]; 

    } 
    if ([stopCountButtonOutlet state]==0){//button depressed=> STOP thread 

     shoudStop=YES; 

     [stopCountButtonOutlet setTitle:@" START INCREMENTING COUNT FROM THREAD "]; 

    } 


} 

- (IBAction)sliderAction:(id)sender { // you can change the value of the variable count manualy. 
count=[sliderOutlet intValue]; 
[sliderDisplayOutlet setIntValue:count];// display value of count 


} 
+1

为什么要创建一个自动释放池,如果你不会耗尽它? – bryanmac

+0

@bryanmac新线程的标准练习。所有的线程方法都应该有一个autorelease池。你如何知道performSelectorOnMainThread:不会将任何autorelease'd对象添加到当前池中? –

+0

我添加了一个autorelease池到我的方法“incrementCountGui”,但它没有帮助。堆大小不断增加我甚至可以在活动监视器上看到它 –

回答

1

1)首先,你应该从未更新从非主线程的线程上的UI!

_通知mainThread要求它更新UI,或使用performSelector:onMainThread:或GCD和get_main_queue()或任何解决方案使主线程更新UI。

[编辑]对不起,我错过了你拨打performSelectorOnMainThread:的部分代码,所以没关系。使用你所需要的线程


2)此外,真的没必要。一般来说,你应该避免使用线程,更喜欢其他技术,比如NSOperationQueues,GCD,甚至是RunLoop调度。

在你的情况,使用线程usleep(5000)只是开销,并会出现很多与多线程相关的问题(请阅读Apple的“并发编程指南”和“线程编程指南”)。

您可以使用重复NSTimer做同样的事情,它将更容易编码和管理,并且会避免你很多麻烦。

+0

计数变量值将在运行时由线程或回调函数修改。这就是我必须能够更新UI的原因,无论计数如何修改。 –

+0

你是对的AliSoftware,你指出我正确的方向与操作队列gcd nstimers.I将做更多的阅读和重写代码。谢谢你的帮助。 –

-1

嗯..让我们尝试释放由performSelectorOnMainThread调用创建的幕后对象,如果有的话。

+(void) updateSliderThread:(id)param 
{ 
    NSAutoreleasePool *myThreadPool=[[NSAutoreleasePool alloc]init]; 
    int drainCount = 0; 
    while (shoudStop==NO) 
    { 
     [ sharedAppInstance performSelectorOnMainThread:@selector(incrementCountGUI:) 
              withObject:nil 
              waitUntilDone:NO]; 
     usleep(5000);// sleep microsec; 

     // Release pooled objects about every 5 seconds 
     if (++drainCount >= 1000) 
     { 
      [myThreadPool release]; 
      myThreadPool = [[NSAutoreleasePool alloc]init]; 
      drainCount = 0; 
     } 
    } 
    [myThreadPool release]; 
} 
+0

刚刚尝试过,但不会阻止内存占用增加。谢谢。 –