我有一个增加变量“int count”值的线程。我想用新的“int count”值更新我的UI,直到我按下停止按钮停止增量。我已经设法更新UI,但内存占用不断增长。它没有显示为内存泄漏,但它是一个分配问题。每次从线程调用UI元素时,堆大小都会增加。我可以清楚地看到仪器泄漏分配部分,我有一些分配,只有在移动触摸UI元素的窗口时才被释放。尽管尝试了一切,我仍无法解决问题。 如果有更好的方法来更新具有“int count”新值的UI元素,请随时告诉我。 感谢
如果您想使用仪器或分配运行以查看问题或查看源代码,我将链接发布到下面的cocoa项目。这是一个只有几行的小项目。
-(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
}
答案 0 :(得分:1)
1)首先,您应该从不从主线程以外的线程更新UI!
_向mainThread发送通知,要求其更新用户界面,或者使用performSelector:onMainThread:
或GCD和get_main_queue()
,或者使主线程更新用户界面的任何解决方案。
[编辑]抱歉,我错过了您致电performSelectorOnMainThread:
的代码部分,这样就可以了。
2)此外,使用线程满足您的需求是非常必要的。一般来说,你应该避免使用线程,更喜欢其他技术,如NSOperationQueues,GCD,甚至是RunLoop调度。
在你的情况下,使用一个线程usleep(5000)只是开销,并且会出现许多与多线程相关的问题(阅读Apple的并发编程指南和线程编程指南)。
您可以使用重复的NSTimer
执行相同的操作,编码和管理会更容易,并且会避免您遇到很多麻烦。
答案 1 :(得分:-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];
}