2009-07-14 22 views

Trả lời

43

Mỗi chương trình chạy trong ít nhất một chủ đề. Bạn có thể nghĩ về từng luồng như một quá trình thực thi chương trình riêng biệt, mỗi luồng chạy song song với các luồng khác.

Nếu bạn có một số loại giao diện người dùng hoặc mã khác cần nghe sự kiện (như cổng mạng), bạn cần một vòng lặp chạy chạy. Mỗi NSThread tự động nhận được vòng lặp chạy của riêng nó, và bạn rất hiếm khi phải tự lo cho mình một cách trực tiếp. Vòng lặp chạy cũng chịu trách nhiệm tạo và giải phóng các nhóm tự động phát hành.

[EDIT: Xem nhận xét để thảo luận thêm về các nhóm tự động phát hành. Điểm quan trọng nhất cần lưu ý là các luồng mới phải đảm bảo thiết lập một nhóm tự động trả lời. Ví dụ, phương pháp được gọi với detachNewThreadSelector (xem dưới đây) cần phải có sau như dòng đầu tiên và cuối cùng của họ:.

NSAutoreleasePool *pool = [ [ NSAutoreleasePool alloc ] init ]; 
    [code here] 
    [pool release]; 

cũng áp dụng cho đề sinh ra bằng các kỹ thuật khác]

Trong chính thread, nơi tất cả các xử lý giao diện người dùng đang diễn ra, vòng lặp chạy là rất quan trọng, vì nó giữ giao diện phản ứng. Đó là lý do tại sao bạn không bao giờ nên chạy mã tốn thời gian trên chủ đề chính: nó sẽ ăn hết thời gian trên luồng và vòng lặp chạy sẽ không được phép chạy thường xuyên, dẫn đến giao diện bị khóa hoặc chậm. Nếu bạn cần thực hiện các phép tính tốn thời gian hoặc giữ một tác vụ đang chạy trong nền, bạn nên tạo một chuỗi mới. Một lần nữa, bạn có thể không phải suy nghĩ về vòng lặp chạy mới được tạo ra. Một cách dễ dàng thực hiện một phương pháp trong một chủ đề mới:

[NSThread detachNewThreadSelector:@selector(theSelector) toTarget:self withObject:nil]; 

truyền thông liên sợi có thể được khôn lanh, và bạn cần phải nhận thức các phương pháp performSelector:onThread:withObject:waitUntilDone:performSelectorOnMainThread:withObject:waitUntilDone: (Great lời khuyên về việc gửi NSNotifications qua đề here.)

Bộ hẹn giờ cũng được xử lý bởi các vòng chạy. Ngược lại với các vòng lặp chạy, bạn thường có thể sử dụng bộ hẹn giờ trực tiếp trong chương trình của mình. Cách dễ nhất để tạo bộ hẹn giờ là:

[self performSelector:@selector(aSelector) withObject:nil afterDelay:1.0]; 

nhưng đôi khi bạn muốn tự mình tạo và quản lý các đối tượng NSTimer, ví dụ để có thể hủy và sử dụng lại bộ hẹn giờ.

An NSTask được sử dụng để chạy chương trình khác dưới dạng tiến trình con của quy trình hiện tại. Đó là một chút tương tự như bắt đầu một thread riêng biệt, nhưng nếu một subprocess treo, chương trình chính của bạn sẽ tiếp tục chạy. Giao tiếp giữa các chương trình cũng rất khác với giao tiếp giữa một số luồng trong cùng một quá trình.

Bạn đã gắn thẻ câu hỏi của mình bằng "iphone" và trên iPhone, bạn sẽ không bao giờ sử dụng NSTask.

NSOperations được sử dụng khi bạn cần phải xử lý một lượng lớn các nhiệm vụ khác nhau, đặt chúng trong hàng đợi và/hoặc xử lý chúng trong chủ đề riêng biệt (mặc dù họ không để chạy trong chủ đề riêng biệt). Nếu ứng dụng của bạn cần tạo một vài chủ đề chuyên biệt, thì không có lý do gì để sử dụng lớp NSOperation. Nhưng nếu bạn thường xuyên sẽ tạo ra các nhiệm vụ (như giao tiếp với một máy chủ) mà phải được theo dõi, NSOperation và NSOperationQueue sẽ có ích.

+0

“Vòng lặp chạy cũng chịu trách nhiệm tạo và giải phóng các nhóm tự động phát hành.” Close. NSApplication thực hiện điều này (trên luồng chính), chứ không phải NSRunLoop. Nếu bạn sinh ra chủ đề của riêng bạn, bạn phải tạo hồ bơi của riêng bạn.(Tôi trích dẫn tài liệu NSAutoreleasePool: “Các đối tượng NSAutoreleasePool được tự động tạo và hủy trong chủ đề chính của ứng dụng dựa trên Bộ Ứng dụng…”.) –

+0

Tôi nghĩ rằng bạn đều sai. Nếu bạn nhìn vào tệp main.m mainplate, * this * là nơi NSAutoreleasePool được tạo và quản lý. KHÔNG có mối tương quan giữa một runloop và một autoreleasepool gần như tôi có thể nói. – Lounges

+0

Vòng lặp chạy có một bể tự động mà nó thoát qua từng chu kỳ. NSApplication không thể chịu trách nhiệm vì nó không có cách nào để thoát nó và nó không gọi mã của bạn. Thường có một hồ bơi autorelease trong chính, nhưng ngoài thời gian khởi tạo nó không bao giờ được sử dụng. –

4
  • NSTimer là đối tượng hẹn giờ, một cách để gọi bộ chọn trên đối tượng trong tương lai.
  • NSThread là một lớp chuỗi. Tôi cho rằng bạn biết chủ đề là gì.
  • NSTask là một lớp quy trình, một cách để chạy một chương trình khác từ chương trình của bạn.
  • NSOperation (Tôi đang thêm vào câu hỏi) là một trừu tượng rất tốt đẹp cho một tác vụ duy nhất. Bạn nhúng hoạt động của mình vào lớp này và bạn có thể dễ dàng thực hiện đồng thời bằng phương tiện của lớp học NSOperationQueue.
  • NSRunLoop là điều khó hiểu nhất. Theo cách nào đó tóm tắt và điều chỉnh cuộc gọi hệ thống unix select() unix, quản lý các nguồn đầu vào và gửi đi các sự kiện và bộ hẹn giờ trên một chuỗi.

Nguyên tắc là Apple Threading Programming Guide.

3

Các câu trả lời khác thực hiện công việc khá tốt khi tính tổng thời gian, nhiệm vụ và chuỗi. Tôi muốn bình luận thêm một chút về NSRunloop vì tôi nghĩ rằng hầu hết các câu trả lời khác vẫn để lại một số rắc rối ở đây. Từ các tài liệu NSRunloop:

Một NSRunLoop đối tượng xử lý đầu vào cho các nguồn như chuột và bàn phím sự kiện từ hệ thống cửa sổ, NSPort đối tượng, và các đối tượng NSConnection. Một đối tượng NSRunLoop cũng xử lý các sự kiện của NSTimer .

cũng

Nói chung, ứng dụng của bạn không cần phải hoặc là tạo hoặc dứt khoát quản lý đối tượng NSRunLoop. Mỗi đối tượng NSThread NSThread, bao gồm chủ đề chính của ứng dụng , có đối tượng NSRunLoop được tự động tạo cho nó nếu cần. Nếu bạn cần truy cập vòng lặp chạy của chuỗi hiện tại, bạn làm như vậy với phương thức lớp currentRunLoop.

Hãy nghĩ NSRunloop là vòng xử lý sự kiện chính và gửi đi cho một chuỗi cụ thể. Nó đọc từ các thiết bị đầu vào, dịch vụ bất kỳ đối tượng nào cần được bảo trì và gửi dữ liệu một cách thích hợp.

+0

Về cơ bản, tất cả xử lý đầu vào của người dùng diễn ra trong chuỗi chính, mặc dù các luồng khác có thể nghe các loại sự kiện khác. Tuy nhiên, trong nhiều chủ đề, runloop không đóng vai trò rõ ràng cho nhà phát triển, như khi bạn chỉ muốn chạy một phép tính tốn thời gian trong nền. – Felixyz

+0

@DharmeshDhorajiya - Vui lòng ngừng đề xuất chỉnh sửa chỉ chèn định dạng mã cho những từ không cần đến. Ở trên là dấu ngoặc kép, không phải mã, và các lớp Cocoa không cần phải có định dạng mã xung quanh chúng. –

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