NSTimer,线程.如何创建一个线程 NSTimer? [英] NSTimer, Threads. How to create a threaded NSTimer?

查看:65
本文介绍了NSTimer,线程.如何创建一个线程 NSTimer?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个 UIView,其中必须有一个访问远程数据库的进程,并且必须使用检索到的结果更新 UITableView.

I'm developing a UIView where there must be a process that accesses to remote database and must update a UITableView with the retrieved results.

为此,我计划使用一个 NSTimer,它每 10 秒运行一次更新过程,在该过程中访问数据库并检索数据.

To do that I'm planning use a NSTimer that runs each 10 seconds the update process where database is accessed and data retrieved.

问题是,如果我在主线程中运行它,视图将被冻结,直到数据被检索和加载.

The problem is that if I run this in the main thread the view will be frozen till the data is retrieved and loaded.

有人知道这是最好的方法吗?任何例子都会受到赞赏.

Anyone knows wicht is the best way to do that? Any example will be apreciated.

谢谢.

编辑----

这是我用来启动 & 的代码停止更新过程:

This is the code that I'm using to start & stop the update process:

-(void)startUpdating
{
    self.isUpdating = YES;

    timerLoop = [[NSTimer scheduledTimerWithTimeInterval:10.0f target:self selector:@selector(listMustBeUpdated:) userInfo:nil repeats:YES] retain];

    [[NSRunLoop mainRunLoop] addTimer: timerLoop
                              forMode: UITrackingRunLoopMode];


}
-(void)stopUpdating
{
    self.isUpdating = NO;

    [timerLoop invalidate];
    [timerLoop release];
    timerLoop = nil;
}

此外,运行应用程序几分钟后,没有错误消息.我认为这是因为内存使用或僵尸,但我已经用仪器测试过,内存使用量为 3.11 Mb(live) &没有僵尸.

In addition, after a few minutes running the app chashes without error message. I think that is because memory usage or zombies, but I've tested with instruments and the memory usage was of 3.11 Mb(live) & no zombies.

也许是因为计时器?

谢谢.

编辑 --- 2

好的,现在这是我用于整个问题的代码,并且在滚动时仍然冻结 UITableView.

Ok, now this is the code I'm using for the whole matter, and still freezing the UITableView while scrolls.

可能是因为是从线程更新而滚动是从主线程执行的?

Maybe is because is updated from the thread and the scrolling is executed from the main thread?

-(void)loadMessagesFromUser:(int)userId toUserId:(int)userToId
{
    fromUserId = userId;
    toUserId = userToId;

    messages = [OTChatDataManager readMessagesFromUser:userId toUser:userToId];

    lastMessageId = [[messages getValueByName:@"Id" posY:[messages CountY]-1] intValue];

    [list reloadData];
}
-(void)messagesMustBeUpdated:(id)sender
{
    if ([NSThread isMainThread]) {
        [self performSelectorInBackground:@selector(updateMessages:) withObject:nil];
        return;
    }


}
-(void)updateMessages:(id)sender
{
    iSQLResult *newMessages = [OTChatDataManager readMessagesFromUser:fromUserId toUser:toUserId sinceLastMessageId:lastMessageId];

    for (int a=0;a<[newMessages CountY];a++)
    {
        [messages.Records addObject:[newMessages.Records objectAtIndex:a]];
        messages.CountY++;
    }

    lastMessageId = [[messages getValueByName:@"Id" posY:[messages CountY]-1] intValue];

    [list reloadData];

}
-(void)startUpdating
{
    self.isUpdating = YES;

    timerLoop = [[NSTimer scheduledTimerWithTimeInterval:10.0f target:self selector:@selector(messagesMustBeUpdated:) userInfo:nil repeats:YES] retain];

}
-(void)stopUpdating
{
    self.isUpdating = NO;

    [timerLoop invalidate];
    [timerLoop release];
    timerLoop = nil;
}

loadMessagesFromUser 可以从 mainThread 调用并访问相同的非原子对象.有可能因为这个原因导致安静的崩溃吗?

loadMessagesFromUser can be called from the mainThread and accesses the same nonatomic object. Is possible the quiet crash because this?

start 和 stop 函数是从主线程调用的.剩下的就是定时器的东西了.

start and stop functions are called from the main thread. The rest is the timer stuff.

感谢您的回复.

推荐答案

首先要考虑的是您如何访问远程数据库.如果您只是通过 HTTP 获取 URL 的内容,则可以使用 NSURLConnection 异步获取内容.您可以将其设置为使用委托或完成块.它将执行 HTTP 请求并在响应到达时通知您,您无需担心线程.

The first thing to consider is how you are accessing the remote database. If you are simply fetching the contents of a URL by HTTP, you can use NSURLConnection to fetch the contents asynchronously. You can set it up to use either a delegate or a completion block. It will perform the HTTP request and notify you when the response has arrived, and you don't need to worry about threads.

如果你正在使用某个库访问远程数据库,并且该库还没有提供异步API,那么你需要担心阻塞主线程.您可以使用 Grand Central Dispatch (GCD) 来避免阻塞主线程.

If you are using some library to access the remote database, and the library doesn't already provide an asynchronous API, then you need to worry about blocking the main thread. You can use Grand Central Dispatch (GCD) to avoid blocking the main thread.

在你的视图控制器中,你需要一个 GCD 队列、一个 NSTimer 和一个标志,以确保你不会启动第二个数据库请求,如果一个数据库请求已经在运行并且需要很长时间时间.

In your view controller, you'll need a GCD queue, an NSTimer, and a flag to make sure you don't start a second database request if one is already running and taking a long time.

@implementation ViewController {
    dispatch_queue_t _databaseQueue;
    NSTimer *_databaseTimer;
    BOOL _databaseQueryIsRunning;
}

您需要清理dealloc中的GCD队列和计时器.

You need to clean up the GCD queue and the timer in your dealloc.

- (void)dealloc {
    if (_databaseQueue)
        dispatch_release(_databaseQueue);
    [_databaseTimer invalidate];
    [_databaseTimer release];
    [super dealloc];
}

您可以在视图出现时启动计时器.

You can start the timer when your view appears.

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    _databaseTimer = [[NSTimer scheduledTimerWithTimeInterval:10 target:self
        selector:@selector(databaseTimerDidFire:) userInfo:nil repeats:YES] retain];
}

当视图消失时,您可以停止计时器.

When the view disappears, you can stop the timer.

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    [_databaseTimer invalidate];
    [_databaseTimer release];
    _databaseTimer = nil;
}

当计时器触发时,如果 GCD 队列中没有正在运行的数据库请求,则在该队列上启动一个数据库请求.

When the timer fires, start a database request on the GCD queue if there isn't one running already.

- (void)databaseTimerDidFire:(NSTimer *)timer {
    if (_databaseQueryIsRunning)
        return;
    _databaseQueryIsRunning = YES;

    // Lazily create the GCD queue.
    if (!_databaseQueue)
        _databaseQueue = dispatch_queue_create("MyDatabaseQueue", 0);

    dispatch_async(_databaseQueue, ^{
        // This block runs off of the main thread.
        NSObject *response = [self performDatabaseRequest];

        // UI updates must happen on the main thread.
        dispatch_sync(dispatch_get_main_queue(), ^{
            [self updateViewWithResponse:response];
        });
        _databaseQueryIsRunning = NO;
    });
}

这篇关于NSTimer,线程.如何创建一个线程 NSTimer?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆