2015-01-20 16 views
5

Cuộc gọi MessageBox.Show bên dưới hiển thị "Bên trong". Đây có phải là một lỗi?Control.Invoke unwraps ngoại lệ bên ngoài và tuyên truyền ngoại lệ bên trong thay vì

private void Throw() 
{ 
    Invoke(new Action(() => 
    { 
     throw new Exception("Outer", new Exception("Inner")); 
    })); 
} 

private void button1_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     Throw(); 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message); // Shows "Inner" 
    } 
} 
+1

Tôi lưu ý rằng 'await Task.Run()' không liên quan. Bạn nên bỏ qua nó từ câu hỏi của bạn, vì nó chỉ phục vụ để đánh lạc hướng từ vấn đề bạn đang yêu cầu. –

+0

Điều này thật thú vị. Nếu chúng ta thêm một ngoại lệ bên trong khác, nó cũng sẽ cho chúng ta điều đó. – Chris

+0

Flaggers: cẩn thận để thực sự đọc câu hỏi trước khi gắn cờ nó như là một bản sao của [này khác] (http://stackoverflow.com/questions/15704711/how-can-i-use-control-invoke-to-throw- một ngoại lệ-đó-wont-be-bỏ qua)? – Juan

Trả lời

5

tôi đã có một cái nhìn tại các nguồn tài liệu tham khảo cho System.Windows.Forms.Control, và mã giao dịch với Invoke trông như thế này:

try { 
    InvokeMarshaledCallback(current); 
} 
catch (Exception t) { 
    current.exception = t.GetBaseException(); 
} 

GetBaseException:

public virtual Exception GetBaseException() 
{ 
    Exception inner = InnerException; 
    Exception back = this; 

    while (inner != null) { 
     back = inner; 
     inner = inner.InnerException; 
    } 

    return back; 
} 

Vì vậy, dường như nó là như thế này thiết kế bởi. Các ý kiến ​​trong nguồn cung cấp không có lời giải thích là tại sao họ làm điều này.

EDIT: Một số trang web mà bây giờ đã biến mất tuyên bố nhận xét này xuất thân từ một chàng trai tại Microsoft:

Dựa trên comfirmation Winform trong hồ sơ, phân tích của chúng tôi là đúng đắn về nguyên nhân gốc rễ và hành vi này là dự định. Lý do là để ngăn người dùng nhìn thấy quá nhiều cơ chế nội bộ của Windows.Forms. Điều này là do hộp thoại báo lỗi mặc định của winform cũng tận dụng Application.ThreadException để hiển thị chi tiết ngoại lệ. .Net Winform nhóm trims các thông tin ngoại lệ khác để các lỗi mặc định hộp thoại sẽ không hiển thị tất cả các chi tiết cho người dùng cuối.

Ngoài ra, một số MSFT đã đề xuất thay đổi hành vi này. Tuy nhiên, .Net Nhóm Winform nghĩ rằng việc thay đổi ngoại lệ để ném là một sự phá vỡ thay đổi và vì lý do này, WinForms sẽ tiếp tục gửi ngoại lệ bên trong nhất đến trình xử lý Application.ThreadException.

+1

Tôi lưu ý rằng cũng có hai báo cáo Kết nối hiện đang bị xóa trên chủ đề, trước đây tại URL http://connect.microsoft.com/VisualStudio/feedback/details/386582/control-invoke-exception-handling và http: // connect.microsoft.com/VisualStudio/feedbackdetail/view/433765/control-invoke-throws-exception-getbaseexception-rather-than-the-actual-exception (nếu bạn cố truy cập các liên kết đó, trang web sẽ báo cáo các trang đó là đã biến mất hoặc bị cấm). Bạn có thể thấy các đoạn nhỏ của mỗi bằng cách tìm kiếm MSDN với "control.invoke exception bên trong" và xem các bản tóm tắt. –

+0

Kết quả tốt đẹp. Không thể tìm thấy mã đó trong ILSPY. – Juan

+1

@Juan Kiểm tra 'InvokeMarshaledCallbacks()' trong 'System.Windows.Forms.Control'. – Chris

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