Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BFTask waitUntilFinished] wait forever. #141

Closed
ufosky opened this issue Sep 7, 2015 · 3 comments
Closed

[BFTask waitUntilFinished] wait forever. #141

ufosky opened this issue Sep 7, 2015 · 3 comments
Assignees

Comments

@ufosky
Copy link

ufosky commented Sep 7, 2015

I write this testcase for reproduce my issue.When runs to line [BFTask waitUntilFinished], it cannot return.

- (void)testAsyncWait {
  NSLog(@"Start call");
  BFExecutor *backgroundExecutor = [BFExecutor executorWithDispatchQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)];
  BFTask *task = [[[BFTask taskFromExecutor:backgroundExecutor withBlock:^id(BFTask *task) {
    NSLog(@"Background call");
    return nil;
  }] continueWithSuccessBlock:^id(BFTask *task) {
    NSLog(@"Background call2");
    return nil;
  }] continueWithExecutor:[BFExecutor mainThreadExecutor] withSuccessBlock:^id(BFTask *task) {
    NSLog(@"Foreground call");
    return @"Test Result";
  }];
  NSLog(@"Wait call");
  [task waitUntilFinished];
  NSLog(@"End call");
  NSLog(@"%@", task.result);
}
@ufosky
Copy link
Author

ufosky commented Sep 7, 2015

I write an alternative implemention of [BFTask waitUntilFinished] for solve this issue:

- (void)waitUntilFinished {
  if ([NSThread isMainThread]) {
    [self warnOperationOnMainThread];
  }
  BOOL finished = NO;
  while (!finished) {
    @autoreleasepool {
      [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
                               beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
      @synchronized(self.lock) {
        if (self.completed) {
          finished = YES;
          continue;
        }
        [self.condition lock];
      }
      NSDate *date = [NSDate dateWithTimeIntervalSinceNow:0.01];
      finished = [self.condition waitUntilDate:date];
      [self.condition unlock];
    }
  }
}

@nlutsenko
Copy link
Member

This sounds about right...
The problem is that a lot of threads usually don't have a run loop attached to them, in addition - I suspect that your wait on condition is changing the flow of waiting, since it is going to bailout early without waiting for a condition to be met if the wait exceeds 0.01s.

We are improving this flow in #135, but that would still leave the spinning the run loop out. I am open to ideas on this. cc @toddreed

@nlutsenko
Copy link
Member

Closing as per no activity and this is working as intended.
@ufosky, let me know if you think this is actionable in some way.
But general suggestion - avoid calling waitUntilFinished at all costs, especially on the main thread.

@nlutsenko nlutsenko self-assigned this Jul 12, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants