2011-09-30 53 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

剛剛嘗試過,但不會阻止內存佔用增加。謝謝。 –