2013-02-17 36 views
5

Tôi đang sử dụng thư viện SocketRocket để xử lý việc kết nối với Websocket. Nó kết nối tốt, nhưng tôi đang cố gắng chạy một số xét nghiệm đơn vị mà trước tiên phải chờ đợi trên WS kết nối. Vì cách duy nhất để biết rằng WS đã kết nối là thông qua phương thức ủy nhiệm của nó, tôi đang gặp khó khăn khi thực hiện quá trình này đồng bộ. Tôi muốn thử nghiệm đơn vị của tôi 'setup phương pháp để chỉ cần tạo kết nối WS và sau đó tearDown đóng nó.Tạm dừng thực thi cho đến khi Websocket kết nối

Tôi đã triển khai hai loại phương thức kết nối cho lớp Websocket của mình. Hai cái đầu tiên khá cơ bản và tôi đã xác minh rằng chúng hoạt động như mong đợi. Điều cuối cùng là nỗ lực của tôi để làm cho nó chặn chủ yếu cho mục đích thử nghiệm. Tôi đã không thể làm cho nó hoạt động và nó chỉ kết thúc chờ đợi mãi mãi, vì vậy tôi tin rằng đó là một sự hiểu lầm khái niệm về phía tôi.

Tôi đoán câu hỏi lớn của tôi là làm thế nào tôi có thể ngừng thực hiện trong một trường hợp thử nghiệm để chờ một cuộc gọi trở lại cho một đại biểu? Vấn đề phát sinh trong các trường hợp thử nghiệm là tôi không thể thực hiện tất cả các thử nghiệm của mình trong khối hoàn thành - phương pháp kiểm tra xem đây là một thành công và kết thúc chương trình.

- (void)connect 
{ 
    DLog(@"Websocket is connecting now"); 
    [_socket open]; 
} 


- (void)connectWithCompletion:(WebsocketConnection)completion 
{ 
    DLog(@"Connecting now..."); 
    [_onConnectBlocksToRun addObject:^{ 
     completion(self.isConnected, self.socket); 
    }]; 
    [_socket open]; 
} 

- (bool)connectBlocking // XXX Doesn't work! 
{ 
    sem = dispatch_semaphore_create(0); 
    [_socket open]; 

    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); 
    return _isConnected; 
} 

#pragma mark - Socket rocket delegate 
- (void)webSocketDidOpen:(SRWebSocket *)webSocket 
{ 
    DLog(@"Websocket has opened"); 
    _isConnected = YES; 
    _socket = webSocket; 

    for (void(^block)() in _onConnectBlocksToRun) { 
     block(); 
    } 
    [_onConnectBlocksToRun removeAllObjects]; 

    if (sem) { 
     dispatch_semaphore_signal(sem); 
     dispatch_release(sem); 
    } 
} 

Trả lời

4

Mặc dù bạn đang đợi semaphore của mình được báo hiệu rằng luồng chính bị chặn nên không có mã nào chạy được. Nếu thư viện của bạn tích hợp với hệ thống runloop, bạn có thể chạy runloop bằng cách sử dụng CFRunLoopRun() thay vì chờ đợi trên semaphore của bạn. Từ cuộc gọi lại đã sẵn sàng của bạn, bạn có thể dừng runloop bằng cách sử dụng CFRunLoopStop(CFRunLoopGetMain()).

+0

Có !! Điều này làm việc hoàn hảo và tôi đã học được điều gì đó mới mẻ. Cảm ơn! – joslinm

Các vấn đề liên quan