gpt4 book ai didi

objective-c - 如何从后台线程更新 cocoa 应用程序中的UI控件

转载 作者:行者123 更新时间:2023-12-03 16:26:18 25 4
gpt4 key购买 nike

以下是.m代码:

#import "ThreadLabAppDelegate.h"
@interface ThreadLabAppDelegate()

- (void)processStart;
- (void)processCompleted;

@end


@implementation ThreadLabAppDelegate

@synthesize isProcessStarted;

- (void)awakeFromNib {
//Set levelindicator's maximum value
[levelIndicator setMaxValue:1000];
}

- (void)dealloc {
//Never called while debugging ????
[super dealloc];
}

- (IBAction)startProcess:(id)sender {
//Set process flag to true
self.isProcessStarted=YES;

//Start Animation
[spinIndicator startAnimation:nil];

//perform selector in background thread
[self performSelectorInBackground:@selector(processStart) withObject:nil];
}

- (IBAction)stopProcess:(id)sender {
//Stop Animation
[spinIndicator stopAnimation:nil];

//set process flag to false
self.isProcessStarted=NO;
}

- (void)processStart {
int counter = 0;
while (counter != 1000) {
NSLog(@"Counter : %d",counter);

//Sleep background thread to reduce CPU usage
[NSThread sleepForTimeInterval:0.01];

//set the level indicator value to showing progress
[levelIndicator setIntValue:counter];

//increment counter
counter++;
}

//Notify main thread for process completed
[self performSelectorOnMainThread:@selector(processCompleted) withObject:nil waitUntilDone:NO];

}

- (void)processCompleted {
//Stop Animation
[spinIndicator stopAnimation:nil];

//set process flag to false
self.isProcessStarted=NO;
}
@end

我需要根据上面的代码清除以下内容。

  1. 如何从 UI 控件中断/取消 processStart while 循环?
  2. 我还需要在主 UI 中显示计数器值,我认为这是通过 PerformSelectorOnMainThread 并传递参数来完成的。只是想知道,还有其他方法吗?
  3. 当我的应用程序启动时,它在事件监视器中显示 1 个线程,但是当我在后台线程中启动 processStart() 时,它会创建两个新线程,这使得总共 3 个线程,直到或除非循环完成。完成循环后我可以看到 2 个线程。所以,我的理解是,当我调用performSelectorInBackground时创建了2个线程,但是第三个线程呢?它是从哪里创建的?
  4. 如果每次调用选择器时线程计数都会增加怎么办?如何控制这种情况,或者我的实现不适合此类要求?

谢谢

最佳答案

how to update UI controls in cocoa application from background thread

简单:Don't.

How to interrupt/cancel processStart while loop from UI control?

processStart之外,设置一个标志变量。在 processStart 内部,检查该标志并退出循环(如果已设置)。

Don't try to “kill” a thread from another thread. It's always a bad idea.通过设置标志来告诉线程是时候停止了,并让线程检查该标志并在适当的时间停止。

I also need to show the counter value in main UI, which i suppose to do with performSelectorOnMainThread and passing argument. Just want to know, is there anyother way to do that?

是的。

When my app started it is showing 1 thread in Activity Monitor, but when i started the processStart() in background thread its creating two new thread,which makes the total 3 thread until or unless loop get finished.After completing the loop i can see 2 threads. So, my understanding is that, 2 thread created when i called performSelectorInBackground, but what about the thrid thread, from where it got created?

使用 Instruments 或 Shark 分析您的应用并查看。它可能是进度指示器的心跳线程。

What if thread counts get increases on every call of selector.How to control that or my implementation is bad for such kind of requirements?

每个performSelectorInBackground:withObject:消息都会启动一个线程。如果您的线程计数没有减少,那是因为您的线程方法没有退出。如果您的线程数太高,(可能)是因为您启动了太多线程。


有更好的方法来做到这一点。

首先,Cocoa 的一般规则是永不 sleep 。可以将其视为特殊的高咖啡因 cocoa 。对于您可能在另一个框架中 sleep 的任何事情,Cocoa 中几乎总是有更好、通常更简单的方法。

考虑到这一点,请查看processStart。它所做的只是每厘米做一些事情。如何最好地做到这一点?

Cocoa 有一个用于此特定目的的类:NSTimer。创建一个计时器,以所需的时间间隔向自己发送一条消息,并通过更新进度条来响应该消息 - 也就是说,您的计时器回调方法本质上应该只是来自 processStart 的循环体,而不需要循环。

顺便说一句,每秒 100 次更新有点过分了。首先,用户并不关心自上次更新进度条以来您已经取得了 1/5 像素的进度。二、the screen only updates about 60 times per second anyway ,所以更新任何可见的东西比这更快是没有意义的。

- (void)dealloc {
//Never called while debugging ????
[super dealloc];
}

假设您将应用程序委托(delegate)放在 MainMenu Nib 中,应用程序对象因此拥有它,但它不知道这一点,因为它只知道应用程序委托(delegate)作为其委托(delegate),这是一种非拥有关系。 (即使是一种所有权关系,也只是两种所有权,应用程序会释放其中一种所有权,这没有帮助。)

但是,应用程序委托(delegate)的生命周期并不重要。它作为应用程序的委托(delegate)的目的意味着它需要与应用程序一样持续,但是当应用程序消失时,进程正在退出,这意味着委托(delegate)也将被释放,作为回收的一部分进程的内存空间。这就是为什么不调用 dealloc 的原因 - 整个进程空间立即消失,而不是一次释放一个对象。

所以,原则上,是的,应用程序委托(delegate)没有被明确清理是有点狡猾的。实际上,不要在其 dealloc 中进行任何临时文件清理(改为使用 applicationWillTerminate:),就可以了。

我通常通过将所有实际工作放入应用程序委托(delegate)拥有的一个或多个其他对象中来解决该问题。应用程序委托(delegate)在 applicationWillFinishLaunching: 中创建这些其他 Controller ,并在 applicationWillTerminate: 中释放它们,因此这些对象确实会获得 dealloc > 消息。问题解决了。

关于objective-c - 如何从后台线程更新 cocoa 应用程序中的UI控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2934413/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com