1

I've this bit of code:

- (IBAction)registerAction:(id)sender {
 [NSThread detachNewThreadSelector:@selector(registerThread) toTarget:self withObject:nil];
}

- (void)registerThread {
 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  

 MyDelegate *delegate = (MyDelegate *)[[UIApplication sharedApplication] delegate];


 NSInteger locationID = [delegate.api checkCoordinate:[NSString stringWithFormat:@"%f,%f",
             location.coordinate.latitude, location.coordinate.longitude]];

 NSNumber *status = [api registerWithUsername:usernameField.text 
          password:passwordField.text email:emailField.text andLocation:locationID];

 [self performSelectorOnMainThread:@selector(registrationDoneWithStatus:) withObject:[NSNumber numberWithInt:1] waitUntilDone:NO];  
    [pool release];   
}

it works nicely, but sometimes I get this error:

void _WebThreadLockFromAnyThread(bool), 0x6157e30: Obtaining the web lock from a thread other than the main thread or the web thread. UIKit should not be called from a secondary thread.

And it seems that only using the delegate I get this error, and I don't know how to resolve.

Thanks in advance :)

patrick
  • 6,533
  • 7
  • 45
  • 66

2 Answers2

3

I've run into the same problem recently.

There may be some active views (eg. UITextField,UITextView). Try resignFirstResponder those views before accessing delegate

negersiu
  • 552
  • 3
  • 20
  • Thank you for that... It was driving me nuts. Was creating an HTTPRequest in a secondary thread, and kept receiving that error message. Turned out a UITextField was firstResponder. Mind you, none of those UI views were being accessed in the thread ! – jyavenard Sep 22 '11 at 08:45
  • you can also use [UIView endEditing:(BOOL)force] to 'make the view or any subview that is the first responder resign (optionally force)' – Alex Zak Feb 13 '12 at 20:12
1

You fix the problem by very carefully thinking through your application's concurrency architecture and ensuring that you aren't exercising anything from a thread that should only be done on the main thread.

In this case, you are causing the UIKit to execute code from a secondary thread. If you were to set a breakpoint on _WebThreadLockFromAnyThread, you would know exactly where.

It is exceedingly atypical to use the app's delegate from a secondary thread in anything but the most extremely controlled circumstances.

tl;dr You can't make an app threaded by detaching a new thread against a random selector.

bbum
  • 162,346
  • 23
  • 271
  • 359
  • What do you mean with: "You can't make an app threaded by detaching a new thread against a random selector."? – patrick Jan 28 '11 at 23:20
  • You can't take any random method and execute that method in a thread via `detachNewThreadSelector:...` and have any hope of the right thing happening. Not saying that is what you did here -- just a general rule. Threading is hard. – bbum Jan 29 '11 at 00:26
  • mhm, how can I set a breakpoint on _WebThreadLockFromAnyThread? – patrick Jan 29 '11 at 12:10
  • In the Xcode debugger... either create a symbolic breakpoint via the UI or enter 'b _WebThreadLockFromAnyThread' in the debugger console. – bbum Jan 29 '11 at 18:58
  • I tried so but it doesn't fire and I didn't figured out why :( however I'm gonna change the code, those api methods were using nsurlconnection sendSynchronousRequest... BTW thanks :) – patrick Jan 29 '11 at 20:42