Đôi khi, nó muốn chặn chuỗi của tôi trong khi chờ sự kiện xảy ra.Chặn và đang chờ sự kiện
Tôi thường làm điều đó một cái gì đó như thế này:
private AutoResetEvent _autoResetEvent = new AutoResetEvent(false);
private void OnEvent(object sender, EventArgs e){
_autoResetEvent.Set();
}
// ...
button.Click += OnEvent;
try{
_autoResetEvent.WaitOne();
}
finally{
button.Click -= OnEvent;
}
Tuy nhiên, có vẻ như điều này nên được một cái gì đó mà tôi có thể giải nén vào một lớp học thông thường (hoặc thậm chí một cái gì đó đã tồn tại trong khuôn khổ).
Tôi muốn để có thể làm điều gì đó như thế này:
EventWaiter ew = new EventWaiter(button.Click);
ew.WaitOne();
EventWaiter ew2 = new EventWaiter(form.Closing);
ew2.WaitOne();
Nhưng tôi thực sự không thể tìm thấy một cách để xây dựng một lớp học như vậy (tôi không thể tìm thấy một cách hợp lệ tốt để vượt qua sự kiện như một đối số). Có ai giúp được không?
Để đưa ra một ví dụ về lý do tại sao điều này có thể có ích, hãy xem xét một cái gì đó như thế này:
var status = ShowStatusForm();
status.ShowInsertUsbStick();
bool cancelled = WaitForUsbStickOrCancel();
if(!cancelled){
status.ShowWritingOnUsbStick();
WriteOnUsbStick();
status.AskUserToRemoveUsbStick();
WaitForUsbStickToBeRemoved();
status.ShowFinished();
}else{
status.ShowCancelled();
}
status.WaitUntilUserPressesDone();
Đây là nhiều hơn nữa súc tích và dễ đọc hơn các mã tương đương bằng văn bản với logic trải ra giữa nhiều phương pháp. Nhưng để thực hiện WaitForUsbStickOrCancel(), WaitForUsbStickToBeRemoved và WaitUntilUserPressesDone() (giả sử rằng chúng ta nhận được một sự kiện khi các thẻ usb được chèn vào hoặc bị loại bỏ), tôi cần phải thực hiện lại "EventWaiter" mỗi lần. Tất nhiên bạn phải cẩn thận để không bao giờ chạy điều này trên GUI-thread, nhưng đôi khi đó là một sự cân bằng đáng giá đối với mã đơn giản hơn.
Việc thay thế sẽ giống như thế này:
var status = ShowStatusForm();
status.ShowInsertUsbStick();
usbHandler.Inserted += OnInserted;
status.Cancel += OnCancel;
//...
void OnInserted(/*..*/){
usbHandler.Inserted -= OnInserted;
status.ShowWritingOnUsbStick();
MethodInvoker mi =() => WriteOnUsbStick();
mi.BeginInvoke(WritingDone, null);
}
void WritingDone(/*..*/){
/* EndInvoke */
status.AskUserToRemoveUsbStick();
usbHandler.Removed += OnRemoved;
}
void OnRemoved(/*..*/){
usbHandler.Removed -= OnRemoved;
status.ShowFinished();
status.Done += OnDone;
}
/* etc */
Tôi thấy rằng khó khăn hơn nhiều để đọc. Phải thừa nhận rằng, nó luôn luôn là dòng chảy sẽ được như vậy tuyến tính, nhưng khi nó được, tôi thích phong cách đầu tiên.
Có thể so sánh với việc sử dụng ShowMessage() và Form.ShowDialog() - chúng cũng chặn cho đến khi một số sự kiện xảy ra (mặc dù chúng sẽ chạy vòng lặp tin nhắn nếu chúng được gọi trên chuỗi gui).
tôi tò mò tại sao chính xác bạn muốn làm điều này ... có thể giúp bạn xây dựng? –
Tôi vẫn không hiểu tại sao bạn muốn chặn chuỗi thay vì chỉ chờ đợi sự kiện - điều đó thực hiện điều gì? –
Bạn đã từng sửa lỗi này chưa? Im có cùng một vấn đề. – Carlo