2012-04-01 72 views
18

tôi đã tạo ra một hàng đợi GCD như thế này:Cách sửa đổi mức độ ưu tiên của hàng đợi GCD tùy chỉnh?

dispatch_queue_t q = dispatch_queue_create("com.testcompany.myqueue", NULL); 

Khi tôi cử nhiệm vụ cho hàng đợi đó, nó là cách chậm hơn so với chỉ đơn giản là thực hiện các nhiệm vụ về các chủ đề chính.

dispatch_async(q, ^(void) { 
    [self performHeavyCalculationAndUpdateUI]; 
}); 

Nghi ngờ của tôi là hàng đợi có mức độ ưu tiên rất thấp theo mặc định. Làm cách nào để thay đổi mức ưu tiên của hàng đợi này? Hay có điều gì khác tôi phải làm?

+3

UIKit chắc chắn nhất đã KHÔNG ** trở thành chủ đề trong iOS 4. Bạn đã nghe thấy ở đâu trên thế giới ?? –

+0

Họ nói rằng tại WWDC. Tôi chắc chắn là 60%. –

+3

Tôi chắc chắn 100% là không. Đó là * không bao giờ * an toàn để sửa đổi giao diện người dùng của bạn từ bất kỳ chủ đề nào khác ngoài chuỗi chính. –

Trả lời

7

Nếu bạn đang làm công cụ UIKit, trong khối của bạn đang chạy trên hàng đợi trung học, cử các bản cập nhật giao diện người dùng trở lại hàng đợi chính từ bên trong hàng đợi thứ qua:

dispatch_async(q, ^(void) { 
    [self performHeavyCalculationAndUpdateUI]; 

    dispatch_async(dispatch_get_main_queue(), ^{ 
     // do my ui update 
    }); 
}); 

Chỉ cần cử vài dòng thực sự cập nhật giao diện người dùng trở lại hàng đợi chính và bạn sẽ thấy nó không phải là vấn đề ưu tiên hàng đợi mà chỉ đảm bảo rằng các cập nhật giao diện người dùng xảy ra trong hàng đợi chính.

+1

Cảm ơn Robert! Tôi đã làm những gì bạn đề nghị. Tuy nhiên, tôi không thể cảm nhận được sự khác biệt. Mã của tôi cũng đọc khung lượt xem và thực hiện phép tính dựa trên các phép đo đó. Phải đọc các hoạt động được gửi đến hàng đợi chính không? –

+0

Không, tôi không nghĩ vậy. Quay trở lại ví dụ thư viện của tôi, hàng đợi thứ cấp của tôi là tìm ra chiều rộng cửa sổ, tạo các nút và hình ảnh, thực hiện rất nhiều thứ như thế, nhưng tôi vừa gọi bản cập nhật thực sự cho khung nhìn (trong trường hợp của tôi là 'addSubview') hàng đợi chính. Nếu các thuộc tính thay đổi của các phần tử của bạn đã có trong khung nhìn, tôi sẽ nghĩ rằng bạn phải gửi các bản cập nhật đó tới hàng đợi chính. – Rob

+0

Để đảm bảo rằng tôi đã gửi cuộc gọi phương thức gây ra các phép tính liên quan đến lượt xem và các thay đổi với dispatch_async (dispatch_get_main_queue(),^{}) ;, nhưng tôi vẫn thấy sự sụt giảm lớn. Khoảng 10 lần chậm hơn nếu tôi không sử dụng GCD. Có điều gì khác có thể khiến GCD chậm lại như thế này không? –

43

Hàng đợi công văn không có mức độ ưu tiên bạn có thể thay đổi.

Bạn có thể thay đổi hàng đợi mục tiêu của hàng đợi nối tiếp bằng cách sử dụng các chức năng dispatch_set_target_queue và sử dụng hàng đợi toàn cầu DISPATCH_QUEUE_PRIORITY_HIGH. Điều này chỉ đảm bảo rằng nó sẽ được lên kế hoạch trước khi bất kỳ khối khác enqueued trên hàng đợi với các ưu tiên mặc định hoặc thấp. Khi khối của bạn bắt đầu thực thi, nó sẽ không chạy nhanh hơn hoặc chậm hơn bất kể hàng đợi được xếp lịch nào.

Vấn đề của bạn rất có thể là việc cập nhật GUI của bạn, xem Robert Ryans trả lời.

+15

Cảm ơn bạn đã giải quyết câu hỏi ban đầu, giúp những người trong chúng tôi tìm thấy điều này mà không gặp sự cố liên quan đến giao diện người dùng trong mã của chúng tôi. –

1

Tôi nghĩ bạn đang thiếu điểm hoạt động không đồng bộ. Và nhận xét của RobertRyan về cập nhật giao diện người dùng không hiển thị nhanh nếu được thực hiện trên hàng đợi phụ là sai. Tất cả các cập nhật giao diện người dùng cần được thực hiện trên hàng đợi chính. Giai đoạn.

Nhưng quay lại GCD và hàng đợi không đồng bộ. @Sven đúng là bạn không thể thay đổi mức ưu tiên của hàng đợi công văn. Hàng đợi trong GCD hoạt động theo kiểu FIFO (First In First Out), do đó thứ tự bạn xếp hàng là thứ tự chúng được thực hiện. Đây là một phần lý do tại sao sử dụng GCD là an toàn luồng; bạn được đảm bảo rằng bạn sẽ không gặp phải bất kỳ vấn đề nào vì ưu tiên hàng đợi FIFO này. Điều thứ hai cần hiểu là khi bạn dispatch_async một hàng đợi, hệ điều hành sẽ không đảm bảo khi hàng đợi đó được xử lý. Đó là một loại nó-và-quên nó loại quá trình. Nếu bạn cần biết khi hàng đợi được xử lý xong, bạn cần thiết lập trình xử lý khối hoàn thành (bạn sẽ nhận thấy nhiều Khung công tác của Apple đã bắt đầu thực hiện điều này) để được thông báo về điều đó. Đây là lý do tại sao Apple đề nghị lồng một cuộc gọi dispatch_async trong cuộc gọi dispatch_async đầu tiên của bạn và yêu cầu chủ đề chính cho cập nhật giao diện người dùng. Vì vậy, mã của bạn sẽ giống như thế này:

dispatch_async(q, ^{ 
    [self performHeavyCalculations]; 
    dispatch_async(dispatch_get_main_queue, ^{ 
     // some UI updates 
    }); 
}); 

Do cách GCD enqueues và dequeues, dispatching cập nhật giao diện người dùng của bạn asyncronously trở lại hàng đợi chính sẽ cho phép cập nhật giao diện người dùng để xảy ra mà không có một sự trì hoãn cảm nhận được cho người dùng. Nếu cập nhật giao diện người dùng của bạn phụ thuộc vào kết quả của performHeavyCalculations, bạn sẽ cần thiết lập trình xử lý hoàn thành hoặc lược đồ ủy quyền để thông báo cho hàng đợi chính khi quá trình này hoàn tất để cập nhật có thể xảy ra. Nếu độ trễ giữa các phép tính và bản cập nhật quá dài, bạn có thể cần xem xét những gì bạn đang làm trong phương pháp tính toán mất quá nhiều thời gian.

+0

Cảm ơn bạn đã làm rõ. Tôi đồng ý rằng bạn nên cập nhật giao diện người dùng trong hàng đợi chính. Tuy nhiên, về điểm không có cập nhật giao diện người dùng cho đến khi performHeavyCalculations được thực hiện, nếu phương thức đó gửi các cập nhật giao diện người dùng trở lại hàng đợi chính, các phương thức đó xảy ra đồng thời với phần còn lại của xử lý performHeavyCalculations. Bạn không phải chờ cho đến khi hoàn tất các cập nhật giao diện người dùng để bắt đầu. – Rob

+0

Bạn không phải đợi, không. Nhưng bạn sẽ chờ đợi. Hàng đợi GCD được xử lý theo ưu tiên FIFO. – jmstone617

+0

Không chính xác. Các cập nhật giao diện người dùng được gửi đến hàng đợi chính bởi hàng đợi thứ cấp tốn thời gian làm _not_ đợi cho đến khi hoàn thành công việc tốn thời gian trong hàng đợi thứ hai. Bạn thấy các cập nhật giao diện người dùng xảy ra mặc dù hàng đợi phụ vẫn bận. Ứng dụng hiện tại của tôi thực hiện chính xác điều đó và nó hoạt động rất tốt. Đó là lý do tại sao tôi đặt công việc tốn thời gian vào hàng đợi riêng ngay từ đầu, vì vậy tôi có thể hiển thị ngay cho người dùng một giao diện người dùng, nhưng một cập nhật liên tục dựa trên tiến độ của một công việc tốn thời gian. – Rob

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