2011-10-06 13 views
5

Tôi đang sử dụng NSTask, nhưng khi tôi khởi chạy tác vụ, nó chặn luồng chính (vì vậy tôi không thể cập nhật nó) cho đến khi tác vụ kết thúc. Đây là mã của tôi:NSTask chặn chủ đề chính

NSString *hostsforping = @"google.es"; 
    pingdata = [[NSTask alloc] init]; 
    [pingdata setLaunchPath: @"/sbin/ping"]; 

    NSArray *pingargs; 
    pingargs = [NSArray arrayWithObjects: @"-c 5", hostsforping, nil]; 
    [pingdata setArguments: pingargs]; 

    NSPipe *pingpipe; 
    pingpipe = [NSPipe pipe]; 
    [pingdata setStandardOutput: pingpipe]; 

    NSFileHandle *pingfile; 
    pingfile = [pingpipe fileHandleForReading]; 

    [pingdata launch]; 

    NSData *pingdata1; 
    pingdata1 = [pingfile readDataToEndOfFile]; 

    NSString *pingstring; 
    pingstring = [[NSString alloc] initWithData: pingdata1 encoding: NSUTF8StringEncoding]; 
    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(taskDidTerminate:) 
               name:NSTaskDidTerminateNotification 
               object:nil]; 
} 
- (void) taskDidTerminate:(NSNotification *)notification { 
    NSLog(@"end"); 
} 

Tôi đã đọc rằng -waitUntilExit không chặn các chủ đề chính, nhưng tôi không sử dụng nó, vì vậy tôi không biết những gì tôi đang làm sai.

Trả lời

11

Chạy tác vụ trên chuỗi nền, readDataToEndOfFile đang chặn luồng chính.

// Offload the method onto a background thread, could also use Grand Central Dispatch 
[self performSelectorInBackground:@selector(startTask) withObject:nil]; 


- (void)startTask { 
    NSString *hostsforping = @"google.es"; 
    NSTask *pingdata = [[NSTask alloc] init]; 
    [pingdata setLaunchPath: @"/sbin/ping"]; 

    NSArray *pingargs; 
    pingargs = [NSArray arrayWithObjects: @"-c 5", hostsforping, nil]; 
    [pingdata setArguments: pingargs]; 

    NSPipe *pingpipe; 
    pingpipe = [NSPipe pipe]; 
    [pingdata setStandardOutput: pingpipe]; 

    NSFileHandle *pingfile; 
    pingfile = [pingpipe fileHandleForReading]; 

    [pingdata launch]; 

    NSData *pingdata1;  
    pingdata1 = [pingfile readDataToEndOfFile]; 

    NSString *pingstring; 
    pingstring = [[NSString alloc] initWithData: pingdata1 encoding: NSUTF8StringEncoding]; 
    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(taskDidTerminate:) 
               name:NSTaskDidTerminateNotification 
               object:nil]; 
} 

- (void) taskDidTerminate:(NSNotification *)notification { 
    // Note this is called from the background thread, don't update the UI here 
    NSLog(@"end"); 

    // Call updateUI method on main thread to update the user interface 
    [self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO]; 
} 
+0

Hoặc, sử dụng khả năng đọcHandler được thực thi tự động, khi tác vụ của bạn được đáp ứng dữ liệu. một cái gì đó được viết trong đường ống. –

1

Vì, bạn sử dụng readDataToEndOfFile, bạn đang ngầm nói rằng NSTask của bạn cần thực thi chặn. Tôi có thể đề nghị bạn quấn mã của bạn xung quanh dấu ngoặc GCD, sử dụng dispatch_async. Ví dụ:

- (void)executeShellScript { 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ 
     NSString *execPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"myScript.sh"]; 

     NSPipe *pipe = [NSPipe pipe]; 
     NSFileHandle *file = pipe.fileHandleForReading; 

     NSTask *task = [[NSTask alloc] init]; 
     task.launchPath = @"/bin/sh"; 
     task.arguments = @[execPath]; 
     task.standardOutput = pipe; 

     [task launch]; 

     NSData *data = [file readDataToEndOfFile]; //readDataToEndOfFile is blocking the main thread. 
     [file closeFile]; 
     NSString *bashOutput = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding]; 

     NSLog (@"shell returned:\n%@", bashOutput); 
    }); 
}