2012-10-12 49 views
5

Tôi cần phải trì hoãn trong một khoảng thời gian nhất định và vẫn cho phép những thứ khác trên cùng một vòng chạy để tiếp tục chạy. Tôi đã sử dụng đoạn mã sau để thực hiện việc này:Cách thích hợp để trì hoãn trong khi cho phép vòng lặp chạy tiếp tục

[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; 

Điều này dường như làm chính xác những gì tôi muốn, ngoại trừ khi chức năng trả về ngay lập tức mà không cần chờ thời gian mong muốn (1 giây).

Có ai cho tôi biết điều gì có thể gây ra điều này không? Và cách thích hợp để chờ đợi trong khi cho phép chạy vòng lặp là gì?

LƯU Ý: Tôi muốn trì hoãn theo cách tương tự như sleep(), chẳng hạn như sau khi trì hoãn, tôi quay trở lại cùng một luồng thực thi như trước.

+0

Bạn muốn trì hoãn điều gì? Bạn đã xem 'dispatch_after' chưa? –

+0

Tôi muốn trì hoãn chuỗi hiện tại, theo cách tương tự như sleep(), ngoại trừ tôi muốn runloop tiếp tục chạy (vì vậy các sự kiện và công cụ khác có thể khởi động) trong thời gian trễ đó. – Locksleyu

Trả lời

8

Bạn nên sử dụng GCD và dispatch_after cho điều đó. Nó là gần đây hơn và hiệu quả (và thread-an toàn và tất cả), và rất dễ sử dụng.

Thậm chí còn có một đoạn mã nhúng trong Xcode, do đó nếu bạn bắt đầu gõ dispatch_after nó sẽ gợi ý đoạn mã và nếu bạn xác nhận nó sẽ viết chuẩn bị 2-3 dòng cho bạn trong mã của bạn :)

Code Snippet suggestion by Xcode

int64_t delayInSeconds = 2.0; 
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
    <#code to be executed on the main queue after delay#> 
}); 
+1

Phương pháp bạn đề cập chạy một đoạn mã khác trên hàng đợi chính, những gì tôi muốn làm về cơ bản là trì hoãn trong một khoảng thời gian và trở về mã mà tôi đã chạy trước đó. Ví dụ, nếu tôi có một vòng lặp for đã in một bản rồi đợi một giây rồi lặp lại. Tôi muốn tuyên bố chỉ đơn giản là 'ngủ' trong một giây và sau đó quay trở lại vòng lặp mà tôi đã chạy trước đó. Điều đó có ý nghĩa? – Locksleyu

+1

Điều đó có nghĩa và không có ý nghĩa. Bạn có thể làm điều này bằng cách làm cho thread của bạn ngủ ('[NSThread sleepForTimeinterval:]' hoặc 'usleep()'?) Nhưng điều này sẽ làm cho một tạm dừng hoạt động, mà không được đề xuất trong các mẫu lập trình OOP thích hợp. Và nếu bạn thực hiện vòng lặp for của bạn trên runloop chính, tất nhiên nó sẽ "đóng băng" ứng dụng của bạn. Đó có thể là thiết kế tồi. – AliSoftware

+2

Giải pháp tôi thấy nếu bạn thực sự muốn thực hiện N lặp đi lặp lại mỗi cách nhau bởi 1 giây là để 'cho (int i = 0; i AliSoftware

1

Sử dụng NSTimer để kích hoạt một cuộc gọi đến một số phương thức sau một thời gian trễ nhất định.

1

The accepted SO answer here sẽ giúp ích. Bạn cũng có thể thực hiện dispatch_afer của David (explained here), đó là một cách cập nhật hơn để làm điều tương tự, bằng cách sử dụng GCD.

Có một số hàm GCD như thế này đáng để biết và chúng rất dễ sử dụng.

+0

Cảm ơn bạn đã phản hồi. Đây không phải là chính xác những gì tôi đang tìm kiếm tuy nhiên (xin lỗi nếu tôi không rõ ràng trong bài viết). Tôi muốn về cơ bản chặn thread hiện tại của tôi (tương tự như một giấc ngủ (1)) và sau đó trở về kiểm soát nơi tôi đã ở trước. Mã bạn đã liên kết để thực hiện "một số mã khác" sau một khoảng thời gian, thay vì chỉ trả lại quyền kiểm soát cho chuỗi của tôi để tôi có thể tiếp tục từ nơi tôi đã dừng lại. Ví dụ tôi đã làm điều này ngoại trừ đôi khi không trì hoãn đúng cách. – Locksleyu

0

Bạn đã thử performSelector:withObject:afterDelay:?

Từ Apple documentation

gọi một phương pháp của người nhận trên thread hiện tại bằng cách sử dụng chế độ mặc định sau khi một sự chậm trễ.

0

Tôi gặp sự cố tương tự và đây là giải pháp của tôi. Hy vọng nó hoạt động cho người khác.

__block bool dispatched = false; 
while (put your loop condition here) 
{ 
    if (dispatched) 
    { 
     // We want to relinquish control if we are already dispatched on this iteration. 
     [ [ NSRunLoop currentRunLoop ] runMode: NSDefaultRunLoopMode beforeDate:[ NSDate date ] ]; 
     continue; 
    } 

    // mark that a dispatch is being scheduled 
    dispatched = true; 

    int64_t delayInNanoSeconds = (int64_t) (0.1 * (float) NSEC_PER_SEC); 
    dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, delayInNanoSeconds); 

    dispatch_after(delayTime, dispatch_get_main_queue(), ^() { 
     // Do your loop stuff here 
     // and now ready for the next dispatch 
     dispatched = false; 
    }); 
} // end of while 
Các vấn đề liên quan