2010-08-13 36 views
8

Có cách nào để yêu cầu một đại biểu chạy trên một chủ đề cụ thể không?Gọi đại biểu về một chủ đề cụ thể C#

Nói rằng tôi có:

CustomDelegate del = someObject.someFunction; 
Thread dedicatedThread = ThreadList[x]; 

Tôi có thể có một nền tảng phù hợp sợi chạy dài và gọi các đại biểu của mình vào nó bất cứ khi nào tôi cần nó. Nó phải là cùng một chủ đề mỗi lần.

[Chỉnh sửa]

Lý do tại sao tôi muốn nó được trên một sợi chuyên dụng là thời gian là tôi Inten để chạy các đại biểu vào nó và đình chỉ các chủ đề sau y mili giây, và tiếp tục các chủ đề khi tôi chạy một đại biểu khác trên đó. Tôi thấy điều này là không thể. Tôi sẽ có một hàng đợi đại biểu và cho phép chức năng chính của luồng đọc và chạy từ nó.

Để làm rõ với một ví dụ cụ thể, tôi có một hệ thống trò chơi với một loạt các chuỗi trình phát. Tôi muốn mỗi playerthread để chạy xử lý sự kiện cho các sự kiện trò chơi trên đó. Nếu trình xử lý sự kiện mất quá nhiều thời gian, tôi muốn có thể tạm dừng trình phát cụ thể đó cho đến khi sự kiện tiếp theo bằng cách tạm dừng chuỗi của nó.

Vì vậy, có một chuỗi chuyên dụng mà tôi có thể chạy nhiều trình xử lý sự kiện, tôi có thể tạm dừng AI của một người chơi cụ thể trong trường hợp nó bị lỗi hoặc mất quá nhiều thời gian.

Trả lời

3

Tôi nghĩ giải pháp tốt nhất là sử dụng các đối tượng Task và xếp hàng chúng vào một số StaThreadScheduler chạy một chuỗi duy nhất.

Hoặc, bạn có thể sử dụng ActionThread trong Nito.Async để tạo một chuỗi bình thường với hàng đợi được tích hợp là Action đại biểu.

Tuy nhiên, cả hai cách này sẽ không trực tiếp giải quyết một nhu cầu khác: khả năng "tạm dừng" một hành động và tiếp tục với một hành động khác. Để làm điều này, bạn cần phải rắc "các điểm đồng bộ" trong mọi hành động và có cách để lưu trạng thái của nó, xếp hàng lại và tiếp tục với hành động tiếp theo.

Tất cả sự phức tạp đó gần như đang đến gần một hệ thống lập lịch trình chuỗi, vì vậy tôi khuyên bạn nên lùi lại một bước và thực hiện nhiều thiết kế lại. Bạn có thể cho phép mỗi hành động được xếp hàng đợi theo số ThreadPool (Tôi khuyên bạn chỉ nên có mỗi đối tượng là đối tượng Task). Bạn vẫn cần phải rắc "các điểm đồng bộ hóa", nhưng thay vì lưu trạng thái và xếp hàng lại chúng, bạn sẽ chỉ cần tạm dừng (chặn) chúng.

+0

Cảm ơn bạn đã chỉ ra ActionThread, trông rất hữu ích. Tôi cần phải đóng gói mã bên ngoài mà tôi có ít quyền kiểm soát trong một chuỗi. Tất cả những gì tôi có là đại biểu cho mã bên ngoài. Nếu tôi có thể đảm bảo rằng đối tượng nằm trong một chuỗi cụ thể, tôi có thể "tạm dừng" đối tượng đó bằng cách chỉ tạm dừng chuỗi. Tôi không nghĩ rằng threadpool sẽ cho phép tôi "tạm dừng" đối tượng độc đáo. – Raynos

+0

Một lời cảnh báo: có thể (thậm chí có khả năng) gây ra tình trạng deadlocks vô tình bằng cách đình chỉ/nối lại các luồng. Nếu có thể, hãy thay đổi mã bên ngoài. Nếu điều đó là không thể, sau đó xem xét sử dụng ưu tiên luồng thay vì tạm dừng/tiếp tục. –

1

Thông thường, tôi khuyên bạn chỉ nên sử dụng hồ bơi chủ đề hoặc BackgroundWorker lớp - nhưng điều này không đảm bảo rằng công việc sẽ xảy ra trên bất kỳ chuỗi cụ thể nào. Không rõ lý do tại sao bạn quan tâm đến chủ đề nào chạy các tác phẩm, nhưng giả thiết rằng nó thực sự quan trọng ...

Bạn sẽ phải vượt qua đối tượng Delegate thông qua một số loại bộ nhớ dùng chung, như hàng đợi. Chủ đề nền sẽ phải xem hàng đợi này, kéo các đại biểu ra khỏi nó khi chúng tồn tại và thực thi chúng.

Nếu nó chỉ ra rằng các hồ bơi thread là chấp nhận được để chạy mã của bạn, bạn luôn có thể sử dụng phương pháp BeginInvoke của các đại biểu để làm như vậy:

// wrap your custom delegate in an action for simplicity ... 
Action someCode =() => yourCustomDelegate(p1, p2, p3, ...); 
// asynchronously execute the currying Action delegate on the threadpool... 
someCode.BeginInvoke(someCode.EndInvoke, action); 
2

Đáng tiếc là có thực sự là không có gì được xây dựng trong để làm điều này trên bất kỳ chủ đề chung nào. Bạn có thể thực hiện việc này bằng cách tạo một lớp bao bọc một Chủ đề và triển khai ISynchonizeInvoke.

Cách tiếp cận đơn giản là tạo hàng đợi xử lý sự kiện trên chuỗi chuyên dụng như LBushkin đề cập đến. Tôi khuyên bạn nên sử dụng lớp học Queue<Action> và gọi trực tiếp cho Đại diện hành động. Bạn có thể thực hiện hầu hết các tác vụ mà bạn sẽ cần bằng cách sử dụng các tác vụ ủy nhiệm ẩn danh.

Cuối cùng, cũng giống như một lời cảnh báo, tôi khuyên bạn nên sử dụng Semaphore hoặc EventWaitHandle thay vì Thread.Sleep trên chuỗi chuyên dụng của bạn. Nó chắc chắn là thân thiện hơn so với thực hiện vòng lặp nền của bạn hơn và hơn nữa khi nó không cần thiết.

+0

Cảm ơn bạn, tôi đã có ý định chạy lặp lại vòng lặp nền. Tôi sẽ xem xét một xử lý sự kiện chờ đợi – Raynos

+1

Tôi đồng ý với cảnh báo về 'Thread.Sleep'; tuy nhiên, op sẽ thực hiện 'SynchronizationContext' thay vì' ISynchronizeInvoke' đã lỗi thời. –

0

Đối với chủ đề bạn tạo, bạn chỉ có thể chỉ định đại biểu ThreadStart khi bạn tạo chúng. Không có điều khoản nào để tiêm một ủy nhiệm khác vào một luồng được tạo ra. Thread Pool là khác nhau ở chỗ nó cho phép bạn gửi các đại biểu cho các chủ đề được tạo trước đó mà nó bắt đầu thay cho bạn.

Không rõ vấn đề bạn đang cố giải quyết. Bạn đang cố gắng thực hiện (hoặc tránh) bằng cách cố gắng chạy nhiều đại biểu trên một chủ đề?

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