2013-06-01 30 views
33

Tôi có một chương trình sử dụng một số chủ đề. Khi tôi hiểu nó, khi thread 0 thoát, toàn bộ chương trình thoát, bất kể bất kỳ chủ đề nào khác có thể vẫn đang chạy.Cách tốt nhất để thoát khỏi chương trình Haskell là gì?

Vấn đề là các chủ đề khác này có thể mở tệp. Đương nhiên, điều này được bao bọc trong mã xử lý ngoại lệ để đóng các tệp trong trường hợp có sự cố. Điều đó cũng có nghĩa là nếu tôi sử dụng killThread (được triển khai qua throwTo), tệp phải cũng đóng trước khi thoát khỏi chuỗi.

Câu hỏi của tôi là, nếu tôi chỉ cho phép thoát khỏi chuỗi 0, mà không cố gắng dừng các luồng khác, tất cả các trình xử lý tệp khác nhau có được đóng độc đáo không? Có bất kỳ đầu ra buffered được flushed?

Tóm lại, tôi có thể chỉ cần thoát hoặc tôi có cần phải tự xóa chuỗi trước không?

+2

Tôi không muốn dựa vào 'killThread' hoặc' exit' để xóa các chủ đề khác cũng như vấn đề vệ sinh lập trình tốt. Tôi cụ tất cả các chủ đề của tôi để lắng nghe tín hiệu làm sạch từ sợi chính để tất cả chúng có thể được tắt một cách duyên dáng. –

+0

Tại sao không thử? IME, hầu hết các hệ điều hành sẽ đóng các tập tin, (tức là không để lại xử lý, fd hoặc rò rỉ khác), nhưng xuất sắc I/O sẽ không được đỏ mặt. –

+1

@GabrielGonzalez Nếu bạn làm theo cách đó, điều đó có nghĩa là một chuỗi sẽ chỉ chấm dứt tại một số điểm nhất định.Nếu bạn quên kiểm tra thường xuyên đủ, hoặc một cái gì đó mất nhiều thời gian hơn dự kiến, bạn có thể nhận được một tình huống mà bạn báo hiệu các chủ đề để chết, và nó không (hoặc chỉ mất một thời gian thực sự dài). Bạn cần phải xử lý ngoại lệ anyway, vậy tại sao không sử dụng 'killThread'? – MathematicalOrchid

Trả lời

3

Từ thử nghiệm của tôi, tôi đã khám phá ra một vài điều:

  1. exitFailure và bạn bè chỉ có tác dụng trong chủ đề 0. (Các tài liệu thực sự nói như vậy, nếu bạn đi đến những rắc rối của việc đọc nó Các chức năng này. chỉ cần ném ngoại lệ, được bỏ qua âm thầm trong các chủ đề khác.)

  2. Nếu ngoại lệ giết chết chuỗi của bạn hoặc toàn bộ chương trình của bạn, mọi chốt mở là không. Điều này thật khó chịu khi bạn đang cố gắng tìm ra chính xác nơi mà chương trình của bạn bị hỏng!

Vì vậy, nó xuất hiện nó nếu bạn muốn công cụ của bạn đỏ mặt trước khi thoát khỏi chương trình, sau đó bạn phải thực hiện điều này. Chỉ cần để cho thread 0 chết không tuôn ra công cụ, không ném bất kỳ ngoại lệ, chỉ âm thầm chấm dứt tất cả các chủ đề mà không cần chạy xử lý ngoại lệ.

3

Bạn có thể sử dụng Control.Concurrent.MVar để đạt được điều này. An MVar về cơ bản là một lá cờ "rỗng" hoặc "đầy đủ". Một chủ đề có thể cố đọc một số MVar và nếu nó trống thì nó sẽ chặn luồng. Bất cứ nơi nào bạn có một chủ đề thực hiện tệp IO, hãy tạo một số MVar cho nó và chuyển cho nó một đối số là MVar. Đặt tất cả các MVar s bạn tạo thành một danh sách:

main = do 
    let mvars = sequence (replicate num_of_child_threads newEmptyMVar) 
    returnVals <- sequence (zipWith (\m f -> f m) 
            mvars 
            (list_of_child_threads :: [MVar -> IO a])) 

Khi một sợi con đã hoàn thành tất cả các hoạt động tập tin mà bạn đang lo lắng về, viết thư cho MVar. Thay vì viết killThread bạn có thể làm

mapM_ takeMVar mvars >> killThread 

và nơi chưa từng chủ đề của bạn sẽ thoát khỏi bằng cách khác, chỉ cần mang tất cả các MVar s.

Xem documentation on GHC concurrency để biết thêm chi tiết.

+3

Tôi nghĩ anh ta hỏi một câu hỏi khác: làm thế nào để ngăn chặn các chủ đề con một cách duyên dáng nếu luồng chủ được thực hiện và không còn muốn chờ kết quả của chúng nữa. Lưu ý phụ: bạn có thể làm những gì bạn mô tả bằng cách sử dụng gói 'async', mà cũng có thêm tiền thưởng của việc nâng cao ngoại lệ được tạo ra trong các chủ đề con nếu bạn 'chờ đợi' trên chúng. –

+0

Khi tôi đọc nó, anh ta lo ngại rằng khi chuỗi gốc thoát ra, các em cũng sẽ thoát ra, có lẽ gây ra các tác dụng phụ không mong muốn nếu chúng được ghi vào tập tin. Nếu thread chính chờ đợi cho các con của nó để hoàn thành tất cả các hoạt động IO tập tin, điều này không còn là một vấn đề. – user2407038

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