Bối cảnh
Một khách hàng đã yêu cầu tôi tìm hiểu lý do tại sao ứng dụng C# của họ (chúng tôi gọi XXX là do một nhà tư vấn đã bỏ chạy) rất lung lay và sửa nó. Ứng dụng điều khiển thiết bị đo lường qua kết nối nối tiếp. Đôi khi thiết bị cung cấp các kết quả đọc liên tục (được hiển thị trên màn hình) và đôi khi ứng dụng cần dừng các phép đo liên tục và chuyển sang chế độ phản hồi lệnh.C# - Làm thế nào để loại bỏ chủ đề nào đọc từ cổng nối tiếp?
Làm thế nào KHÔNG để làm điều đó
Đối với các phép đo liên tục, sử dụng XXX System.Timers.Timer
cho xử lý nền của đầu vào nối tiếp. Khi bộ đếm thời gian kích hoạt, C# chạy bộ đếm thời gian ElapsedEventHandler
của bộ hẹn giờ bằng cách sử dụng một số luồng từ nhóm của nó. Trình xử lý sự kiện của XXX sử dụng chặn commPort.ReadLine()
với thời gian chờ một vài giây, sau đó gọi lại cho người được ủy quyền khi một phép đo hữu ích đến trên cổng nối tiếp. Tuy nhiên, phần này hoạt động tốt, tuy nhiên ...
Khi thời gian dừng đo thời gian thực và yêu cầu thiết bị thực hiện điều gì đó khác, ứng dụng sẽ cố tạm dừng xử lý nền từ luồng GUI bằng cách đặt Enabled = false
của bộ hẹn giờ. Tất nhiên, điều đó chỉ thiết lập một cờ ngăn chặn các sự kiện tiếp theo, và một luồng nền đã chờ đợi cho đầu vào nối tiếp tiếp tục chờ đợi. Chủ đề GUI sau đó gửi một lệnh tới thiết bị và cố gắng đọc trả lời - nhưng câu trả lời được nhận bởi chuỗi nền. Bây giờ các chủ đề nền trở nên bối rối vì nó không phải là đo lường dự kiến. Các thread GUI trong khi đó trở nên bối rối vì nó không nhận được câu trả lời lệnh dự kiến. Bây giờ chúng tôi biết lý do tại sao XXX rất dễ hỏng.
thể Phương pháp 1
Trong một ứng dụng tương tự, tôi đã sử dụng một sợi System.ComponentModel.BackgroundWorker
cho phép đo tự chạy. Đình chỉ xử lý nền tôi đã làm hai điều trong thread GUI:
- gọi các
CancelAsync
phương pháp trên thread, và - gọi
commPort.DiscardInBuffer()
, gây ra một cấp phát (bị chặn, chờ đợi) cư đọc trong thread nền ném một sốSystem.IO.IOException "The I/O operation has been aborted because of either a thread exit or an application request.\r\n"
.
Trong chủ đề nền, tôi bắt ngoại lệ này và dọn sạch kịp thời và tất cả hoạt động như dự định. Thật không may DiscardInBuffer
kích hoạt ngoại lệ trong đọc chặn của một luồng khác không phải là hành vi được ghi lại ở bất cứ nơi nào tôi có thể tìm thấy và tôi ghét dựa vào hành vi không có giấy tờ. Nó hoạt động vì nội bộ DiscardInBuffer
gọi API Win32 PurgeComm, làm gián đoạn việc chặn đọc (hành vi được ghi lại).
thể Phương pháp 2
Trực tiếp sử dụng phương pháp BaseClass Stream.ReadAsync
, với một mã thông báo màn hủy, sử dụng một cách hỗ trợ gián đoạn nền IO.
Bởi vì số lượng ký tự được nhận là biến (chấm dứt bởi một dòng mới), và không có phương pháp ReadAsyncLine
tồn tại trong khuôn khổ, tôi không biết nếu điều này là có thể. Tôi có thể xử lý từng ký tự riêng lẻ nhưng sẽ có hiệu năng (có thể không hoạt động trên các máy chậm, trừ khi tất nhiên bit kết thúc dòng đã được triển khai trong C# trong khung công tác).
Phương thức có thể 3
Tạo khóa "Tôi có cổng nối tiếp". Không ai đọc, viết hoặc loại bỏ đầu vào từ cổng trừ khi họ có khóa (bao gồm lặp lại việc chặn đọc trong chủ đề nền). Cắt các giá trị thời gian chờ trong chuỗi nền đến 1/4 giây để có thể chấp nhận được hiệu ứng GUI mà không cần quá nhiều chi phí.
Câu hỏi
Có ai có giải pháp đã được chứng minh để giải quyết vấn đề này không? Làm cách nào để có thể ngừng xử lý nền của cổng nối tiếp? Tôi đã googled và đọc hàng chục bài viết bemoaning C# SerialPort
lớp học, nhưng đã không tìm thấy một giải pháp tốt.
Cảm ơn trước!
Bạn chưa tập trung vào các vấn đề thực sự, nó là System.Timers.Timer. Loại bỏ nó và sử dụng một bộ đếm thời gian đồng bộ thay thế. –
Xin lỗi Hans, tôi không theo. Không có phương pháp nào có thể 1-3 sử dụng System.Timers.Timer; Bạn gợi ý gì? –