Ngoài kỹ thuật semaphore được đề cập đầy đủ trong các câu trả lời khác, giờ đây chúng ta có thể sử dụng XCTest trong Xcode 6 để thực hiện các kiểm tra không đồng bộ thông qua XCTestExpectation
. Điều này giúp loại bỏ sự cần thiết của semaphores khi kiểm tra mã không đồng bộ. Ví dụ:
- (void)testDataTask
{
XCTestExpectation *expectation = [self expectationWithDescription:@"asynchronous request"];
NSURL *url = [NSURL URLWithString:@"http://www.apple.com"];
NSURLSessionTask *task = [self.session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
XCTAssertNil(error, @"dataTaskWithURL error %@", error);
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSInteger statusCode = [(NSHTTPURLResponse *) response statusCode];
XCTAssertEqual(statusCode, 200, @"status code was not 200; was %d", statusCode);
}
XCTAssert(data, @"data nil");
// do additional tests on the contents of the `data` object here, if you want
// when all done, Fulfill the expectation
[expectation fulfill];
}];
[task resume];
[self waitForExpectationsWithTimeout:10.0 handler:nil];
}
Vì lợi ích của các độc giả trong tương lai, trong khi kỹ thuật semaphore là một kỹ thuật tuyệt vời khi thực sự cần thiết, tôi phải thú nhận rằng tôi thấy quá nhiều nhà phát triển mới, không quen thuộc với các mẫu lập trình không đồng bộ tốt, hấp dẫn quá nhanh đối với semaphores như một cơ chế chung để tạo ra sự không đồng bộ thói quen cư xử đồng bộ. Tệ hơn nữa là tôi đã thấy nhiều người trong số họ sử dụng kỹ thuật semaphore này từ hàng đợi chính (và chúng ta không bao giờ nên chặn hàng đợi chính trong các ứng dụng sản xuất).
Tôi biết đây không phải là trường hợp ở đây (khi câu hỏi này được đăng, không có một công cụ hay như thế XCTestExpectation
, ngoài ra, trong các bộ thử nghiệm này, chúng tôi phải đảm bảo thử nghiệm không kết thúc cho đến khi cuộc gọi không đồng bộ được thực hiện). Đây là một trong những tình huống hiếm hoi trong đó kỹ thuật semaphore để chặn luồng chính có thể là cần thiết.
Vì vậy, với lời xin lỗi của tôi cho tác giả của câu hỏi ban đầu này, người mà kỹ thuật semaphore là âm thanh, tôi viết lời cảnh báo này cho tất cả những nhà phát triển mới xem kỹ thuật semaphore này và xem xét áp dụng nó trong mã của họ như một cách tiếp cận chung để xử lý sự không đồng bộ phương pháp: Được cảnh báo rằng chín lần trong số mười, kỹ thuật semaphore khôngcách tiếp cận tốt nhất khi gặp các hoạt động không đồng bộ. Thay vào đó, hãy tự làm quen với các mẫu khối / đóng hoàn thành, cũng như các mẫu và thông báo giao thức ủy nhiệm. Đây thường là những cách tốt hơn để xử lý các tác vụ không đồng bộ, thay vì sử dụng các từ ngữ để làm cho chúng hoạt động đồng bộ. Thông thường có những lý do chính đáng để các tác vụ không đồng bộ được thiết kế để hoạt động không đồng bộ, vì vậy hãy sử dụng mẫu không đồng bộ đúng thay vì cố gắng làm cho chúng hoạt động đồng bộ.
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
bằngwhile (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]]; }