Objective-C - Canceling a thread?

久未见 提交于 2019-12-21 22:46:15

问题


I have a search function in my app where the user types in the textField, and as the text changes I am searching the local database and populating data in a table.

The search might take anywhere between 1 to 10 seconds depending on the text entered, so I decided to use a thread. Every time the text changes I want to cancel the thread (If running already), and start it again with the new keyword. The problem is that according to the documentation calling cancel doesn't guaranty that the thread will be killed. So what is the solution here?

Is there any way to kill a thread?

- (void)populateData
{
   if (self.searchThread.isExecuting)
   {
       [self.searchThread cancel];
   }

   [self.searchThread start];
}

- (void)populateDataInBackground
{
   @autoreleasepool
   {
      // get data from db
      // populate table on main thread
   }
}

回答1:


You don't want the thread to die necessarily, as it will be reused later (making threads is expensive). What you should do is break your work into as many pieces as you can, and in between each piece check to see if your thread's isCancelled property is YES. If so, return without the update.

[NSThread currentThread] should return your thread while you are inside populateDataInBackground




回答2:


I ended up modifying my dataStorage to return 10 items at a time, just for testing. I might use another number later. This way I can exit the thread in my while loop.

Another advantage is that this way I can populate the table as I go through the items, instead of waiting for all data to be retrieved.

@interface ViewController

@property (nonatomic, strong) NSthread *searchThread;

@end

@implementation ViewController
@synthesize searchThread = _searchThread;

- (void)populateData
{
   [self.searchThread cancel];

   self.searchThread = [[NSThread alloc] initWithTarget:self selector:@selector(populateDataInBackground) object:nil];
   [self.searchThread start];
}

- (void)populateDataInBackground
{
   @autoreleasepool
   {
      [self.array removeAllObjects];

      // I added paging functionality to my sql, so I get let's say 10 records at a time
      while (/*has data*/)
      {
          NSArray *arrayOf10 = [self.dataStorage getdatafromIndex:startingIndex withCount:10];

          if ([[NSThread currentThread] isCancelled])
               [NSThread exit];

          [self.array addObjects:arrayOf10];
          [self.tableView performSelectorOnMainThread:@Selector(reloadData) withObject:nil waitUntilDone:NO];
      }
   }
}

@end



回答3:


One of a few possible solutions would include this:

Set some "BOOL" semaphore / property from your main thread (e.g. "searchNow") and read it periodically while you're going through your "populateData" background thread / task.

If the state changes to "NO" (assuming "searchNow" == YES implies that the task should continue), then exit your background thread.



来源:https://stackoverflow.com/questions/11553863/objective-c-canceling-a-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!