我的主程序产生一个线程,执行以下命令:
// alloc autorelease pool somewhere before
NSArray *blah = [NSArray arrayWithObject: @"moo"];
[self performSelectorOnMainThread: @selector(boonk:) withObject: blah
waitUntilDone: NO];
// release autorelease pool somewhere after
Run Code Online (Sandbox Code Playgroud)
现在,这似乎对我来说是错误的,因为自动释放池可以在选择器boonk:完成执行之前释放,这会导致崩溃.
所以,我接下来的自然行动将是:
// alloc autorelease pool somewhere before
NSArray *blah = [[NSArray alloc] initWithObject: @"moo"];
[self performSelectorOnMainThread: @selector(boonk:) withObject: blah
waitUntilDone: NO];
// release autorelease pool somewhere after
- (void)boonk: (id)data
{
// do something with data
[data release]; // release the ref count the thread added
}
Run Code Online (Sandbox Code Playgroud)
这绝对没有错误,但......似乎不自然.是否有一个objective-c引用计数约定或协议来处理这种情况(交叉线程等待发布),或者是第二种解决方案,它的工作方式是什么?
multithreading memory-management conventions objective-c nsthread
我正在编写一个必须与通过USB连接的设备进行通信的应用程序.应用程序在固定时间从设备轮流发送和接收数据.所有Rx/Tx都发生在一个单独的线程中,否则UI将被阻止.基本结构看起来基本上是这样的.(自动释放池和省略的东西)
-(void)comThread:(id)arg {
while(state == kIsConnected) {
// let timers run
[runLoop runUntilDate:[NSDate distantFuture]];
// handle data
if(rxTxState == kRx) {
// do some stuff to pass data to upper layers
rxTxState = kTx;
}
if(rxTxState == kTx) {
// do some stuff to send data
rxTimeoutTimer = [NSTimer scheduledTimer....];
}
}
}
Run Code Online (Sandbox Code Playgroud)
在发送数据之后,应用程序等待接收数据或者rxTimeoutTimer发送导致重新发送数据包的数据.rx操作有效,因为底层使用异步系统调用并调用一个看起来基本像这样的rx处理程序.
-(void)receiveData:(NSData*)data{
[rxQueue addObject:data];
[rxTimeoutTimer invalidate]; // cancel timeout
}
Run Code Online (Sandbox Code Playgroud)
有一种(简单的)[runLoop runUntilDate:]退出方式receiveData:吗?Apple文档说删除所有计时器源并不能保证RunLoop退出.我读了一些关于打电话的事情,performSelector:onThread:...但它要么不起作用,要么我没有明白这一点.
谢谢.
在iPhone上,我想在一个单独的线程中对图像进行一些操作.我不想处理semiphores,锁定等,而是使用'One Object,One Thread'方法安全地编写这个并发操作.我不确定将对象复制到新线程的正确方法是什么,以便在主线程中不访问该对象.我使用'复制'方法吗?如果是这样,我是在线程之前还是在线程内部这样做?
...
-(void)someMethod{
UIImage *myImage;
[NSThread detachNewThreadSelector:@selector(getRotatedImage:) toTarget:self withObject:myImage];
}
-(void)getRotatedImage:(UIImage *)image{
...
...
UIImage *copiedImage = [image copy];
...
...
}
Run Code Online (Sandbox Code Playgroud) I'm trying to make a test app which measures the performance for threads. However, I'm trying to set an image to imageview on a thread and it's not updating. In fact, the methods setImage1 and setImage2 aren't even getting called. Any ideas? Look at the code for details
#import "UntitledAppDelegate.h"
#import <QuartzCore/QuartzCore.h>
@implementation UntitledAppDelegate
@synthesize window, imageView1, imageView2, label1, label2, label0;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[window makeKeyAndVisible];
return YES;
}
-(IBAction) startSeparate:(id) sender
{
imageView1.image = imageView2.image = …Run Code Online (Sandbox Code Playgroud) 问题很简单:我的应用程序控制每次启动时是否有更新.如果有更新,弹出窗口将显示是或否选择.当用户点击是4方法开始.这些方法下载xml文件并上传CoreData.这是警报的代码:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex==1) {
[self showActivityViewer];
[self downloadControlAndUpdatePoi];
[self downloadControlAndUpdateItinerari];
[self downloadControlAndUpdateArtisti];
[self downloadControlAndUpdateEventi];
[self hideActivityViewer];
NSLog(@"AGGIORNA");
} else {
NSLog(@"NON AGGIORNARE");
return;
}
}
Run Code Online (Sandbox Code Playgroud)
但是有一个问题:当用户点击是时,警报不会消失并保留在屏幕上,直到所有方法都完成.所以我尝试这个其他代码:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex==1) {
[self showActivityViewer];
[NSThread detachNewThreadSelector:@selector(startDownloads) toTarget:self withObject:nil];
[self hideActivityViewer];
NSLog(@"AGGIORNA");
} else {
NSLog(@"NON AGGIORNARE");
return;
}
}
-(void)startDownloads {
NSInvocationOperation *opPoi=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadControlAndUpdatePoi) object:nil];
NSInvocationOperation *opItinerari=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadControlAndUpdateItinerari) object:nil];
NSInvocationOperation *opArtisti=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadControlAndUpdateArtisti) object:nil];
NSInvocationOperation *opEventi=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadControlAndUpdateEventi) object:nil]; …Run Code Online (Sandbox Code Playgroud) 我需要在后台和前台完成一项长时间运行的任务.这会更新核心数据.因此,为了维护UI响应,我创建了另一个线程,我使用不同的managedObjectContext(MOC).因此,计时器在后台和前台设置,并在状态发生变化时被适当地停用.在任务开始之前和任务完成之后,当我按下主页按钮时,它会正确调用两个委托方法但在任务处于活动状态时按下主页按钮屏幕更改并且UI挂起(变为空白)但是两个委托方法不是正确调用,应用程序不会终止.我找不到这种情况发生的原因.如果有人可以提供帮助,将会很有帮助.
我将附上所需的代码:
-(void) startTimerThread
{
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
// Add code here to do background processing
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
[context setPersistentStoreCoordinator:[(AppDelegate *)[[UIApplication sharedApplication] delegate] persistentStoreCoordinator]];
self.managedObjectContext = context;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(mergeChanges:)
name:NSManagedObjectContextDidSaveNotification
object:context];
NSLog(@"managedObjContext : %@\n",self.managedObjectContext);
[self getDataFromFile];
dispatch_async( dispatch_get_main_queue(), ^{
// Add code here to update the UI/send notifications based on the
// results of the background processing
[[NSNotificationCenter defaultCenter] postNotificationName:@"ReloadAppDelegateTable" object:nil];
[context release];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSManagedObjectContextDidSaveNotification
object:context];
});
});
}
- (void)applicationDidEnterBackground:(UIApplication …Run Code Online (Sandbox Code Playgroud) 我经历了很多网站,但仍然没有答案.
我有一个方法,假设void xyz(),它会自动被调用从视图控制器 后每隔3秒.
我不知道该使用什么,我是否必须使用NSThread或PerformSelector.
指导我们.
这是我的代码:
@interface MyObject ()
@property(nonatomic) dispatch_queue_t queue;
@end
@implementation MyObject {
NSThread *_check;
}
- (id)init {
self = [super init];
if (self) {
_queue = dispatch_queue_create("com.Thread.queue", NULL);
dispatch_async(_queue, ^{
_check = [NSThread currentThread]; //for ex. thread number = 3
//some code here...
});
}
return self;
}
- (void)someMethod:(MyObjClass *)obj {
dispatch_async(_queue, ^{
//need th
if (_check != [NSThread currentThread]) { // it is sometimes number 3, but sometimes it changes
NSLog(@"Thread changed.");
}
[obj doSmth]; //got crash if …Run Code Online (Sandbox Code Playgroud) 我想在默认NSNotificationCenter调用的方法中使用postNotificationName停止指示器的动画.所以我在主线程上做这个
-(void)method
{
...
[ind performSelectorOnMainThread:@selector(stopAnimating) withObject:nil waitUntilDone:NO];
}
Run Code Online (Sandbox Code Playgroud)
它确实无效.方法被正确调用,任何其他被调用的选择器完成它们的工作但不是stopAnimating.我把[ind stopAnimating]放在另一个函数中,然后通过performSelectorOnMainThread调用它,但它仍然无效.
根据文档 CLLocationManagerDelegate
从启动相应位置服务的线程中调用委托对象的方法。该线程本身必须具有活动的运行循环,就像在应用程序主线程中找到的那样。
我不清楚这是否意味着要在后台线程上接收位置管理器更新,我们必须在该后台线程上实例化位置管理器还是直接startUpdatingLocation()在该线程上调用方法。
无论如何,这解释了当a 从后台线程上启动时没有收到来自的任何事件时的问题:CLLocationManagerDelegateCLLocationManager
该线程本身必须具有活动的运行循环
如果我理解运行循环的功能正常,那么所有NSThreads运行循环都会实例化,但是只有在为线程分配一些工作后,运行循环才会运行。因此,要CLLocationManager在后台线程上正确发送事件,我们需要将线程的运行循环设置为永久循环,以便它可以在CLLocationManager调用到达时处理它们。
这个问题提出了一种确保运行循环正在运行的合理解决方案,但是作者暗示这是一种处理器昂贵的方式。
另外,根据线程文档,
就内存使用和性能而言,线程化会给您的程序(和系统)带来实际成本
我很欣赏我们都通过使用Grand Central Dispatch来使用大量线程,但是Grand Central Dispatch可能会减轻其内部线程管理中的许多麻烦。
所以我的第一个问题是,是否值得通过连续运行的运行循环设置后台线程,以便在后台线程上处理位置事件,或者与离开管理器相比,这会涉及不合理的额外处理量吗?在主线程上?
其次,如果值得的话,是否有使用Grand Central Dispatch进行此操作的好方法。据我了解的文档,Grand Central Dispatch管理自己的线程,而我们无法知道给定块将在哪个线程上执行。我想我们可以简单地执行通常的运行循环代码,以使我们CLLocationManager实例化的任何线程的运行循环都在循环中连续运行,但是这可能不会影响独立分配给Grand Central Dispatch的其他任务吗?
multithreading nsthread grand-central-dispatch cllocationmanager swift
nsthread ×10
ios ×5
iphone ×4
objective-c ×4
cocoa ×2
background ×1
concurrency ×1
conventions ×1
ios5 ×1
macos ×1
nsoperation ×1
nsrunloop ×1
nstimer ×1
swift ×1
xcode ×1