2011-01-26 30 views
12

Hộp thoại cửa sổ WPF được hiển thị bằng cách sử dụng phương pháp ShowDialog trong lớp Window như khi một nút được nhấn trên cửa sổ chính, như thế này.WPF ShowDialog nuốt ngoại lệ trong khi tải cửa sổ

 private void button1_Click(object sender, RoutedEventArgs e) 
     { 
      try 
      { 
       var window = new Window1(); 
       window.ShowDialog(); 
      } 
      catch (ApplicationException ex) 
      { 
       MessageBox.Show("I am not shown."); 
      } 
     } 

Cửa sổ có một sự kiện Loaded đăng ký trong XAML như thế này:

<Window x:Class="Stackoverflow.Window1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="Window1" Loaded="Window_Loaded"> 
    <Grid /> 
</Window> 

Một ngoại lệ được ném vào các sự kiện Window_Loaded

private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 
     throw new ApplicationException(); 
    } 

Tuy nhiên ngoại trừ không được đánh bắt bởi các bắt xung quanh cuộc gọi ShowDialog, cũng không gọi lại. Ngoại lệ bị nuốt và cửa sổ vẫn hiển thị.

Tại sao điều này xảy ra và tôi sẽ xử lý ngoại lệ trong sự kiện Window_Loaded của cửa sổ WPF như thế nào? Tôi có phải nắm bắt nó trong xử lý sự kiện và Vứt bỏ cửa sổ theo cách thủ công không?

Trong WinForms bạn cần phải gọi Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException)

để cho trường hợp ngoại lệ bong bóng qua ShowDialog gọi. Có một chuyển đổi tương tự mà cần phải được thiết lập trên WPF?

+0

Tôi đã cố gắng tái tạo tình huống của bạn nhưng không thành công. Trường hợp ngoại lệ bị bắt theo cách thông thường. Tôi cho rằng, bạn đã đơn giản hóa mã, nhưng có vẻ như điểm chính là chi tiết. Cung cấp cho họ và tôi sẽ cố gắng giúp đỡ. –

+0

Cảm ơn bạn đã cố gắng tái sản xuất. Tôi đã sao chép vấn đề trong một ví dụ rất đơn giản từ nơi tôi lấy mã nguồn đã đăng. Tôi đang sử dụng VS2010. Tôi sẽ chỉnh sửa câu hỏi của mình và thêm một số thông tin có liên quan để tái tạo. – vidstige

Trả lời

7

Tôi chỉ thấy sự cố này trên máy x64, với mã được biên dịch với Bất kỳ Cpu nào. Thay đổi chương trình của bạn để biên dịch như x84 có thể sửa chữa nó, nhưng tôi đã có vấn đề ở đó bản thân mình tùy thuộc vào hội đồng của chúng tôi.
Đề xuất mã duy nhất của tôi là như sau, và thậm chí sau đó nó không được đảm bảo để nhặt nó lên. Nắm bắt ngoại lệ và ném lại vào một Nhân viên nền.

private void Window_Loaded(object sender, RoutedEventArgs e) 
{ 
    try 
    { 
     /// your code here... 
     throw new ApplicationException(); 
     /// your code here... 
    } 
    catch (Exception ex) 
    { 
     if (IntPtr.Size == 8) // 64bit machines are unable to properly throw the errors during a Page_Loaded event. 
     { 
      BackgroundWorker loaderExceptionWorker = new BackgroundWorker(); 
      loaderExceptionWorker.DoWork += ((exceptionWorkerSender, runWorkerCompletedEventArgs) => { runWorkerCompletedEventArgs.Result = runWorkerCompletedEventArgs.Argument; }); 
      loaderExceptionWorker.RunWorkerCompleted += ((exceptionWorkerSender, runWorkerCompletedEventArgs) => { throw (Exception)runWorkerCompletedEventArgs.Result; }); 
      loaderExceptionWorker.RunWorkerAsync(ex); 
     } 
     else 
      throw; 
    } 
} 
+0

wow, nó hoạt động ... Điều đó thực sự kỳ lạ và đáng sợ. Tôi không nghĩ rằng tôi muốn tìm hiểu thêm về điều này ngay bây giờ. :) Tôi nghĩ đó là một thiết kế WPF. Cảm ơn rất nhiều! – vidstige

+4

oh, một sidenote không ném ngoại lệ một lần nữa như thế này "ném cũ;" - Tốt hơn để trở lại. Như thế này "ném"; – vidstige

+0

Tôi đã xóa cú ném "cũ".Nó có nhiều hơn cho sự rõ ràng hơn bất cứ điều gì khác. Chúng tôi đã có một tình huống mặc dù, IntPtr.Size trả về một 4 trên một máy x64 và ngoại lệ vẫn swollowed khi tải một cửa sổ thông qua refleciton từ lắp ráp khác, vì vậy tôi sẽ không nói đây là một giải pháp 100%. Việc loại bỏ câu lệnh If sẽ sửa lỗi này. – midspace

0

Tôi đã gặp sự cố tương tự và cố gắng hiểu nơi nó đang đến là bực bội. Có một vài điều có thể gây ra vấn đề.

  • Bạn có gọi gì trước khi gọi phương thức InitializeComponent() hay không; ? Trước đây tôi đã có một phương thức gọi các phần tử xaml chưa được khởi tạo.
  • Bạn đã thử nhấn F10 để khởi động ứng dụng, sử dụng Step Over sẽ cho phép bạn xem quá trình khởi động chính xác chưa?
  • Bạn đã kiểm tra tên của mình chưa? XAML có thể nuốt các lỗi như các phương thức được viết sai chính tả, và sau đó một ngoại lệ được ném vào thời gian chạy, các nhà cung cấp DataSet đặc biệt đúng này. Bạn sẽ ngạc nhiên những gì bạn có thể nhận được ngay với.
  • Nắm bắt một ngoại lệ cho việc mở biểu mẫu là khá cơ bản, tôi muốn xem xét bất kỳ người phụ thuộc nào (Dữ liệu hoặc XAML ràng buộc) và xử lý những người đầu tiên.

Hope những điểm giúp .......

+0

* không có metod nào khác được hiển thị ngoài những gì được nêu trong câu hỏi. Các InitializeComponents là một mình trong constructor của cả hai cửa sổ. – vidstige

+0

* Điểm tốt. Tôi đoán một cách là chạy tất cả các mã có thể ném trước khi hộp thoại được hiển thị. – vidstige

1

tôi cũng xây dựng lại câu trả lời của bạn trong Visual Studio 2010 trong một dự án WPF 3.5 trống.

Dự án hoạt động như dự kiến, tức là Window_Loaded đã ném ngoại lệ và sự kiện này đã bị sự kiện nhấp vào nút phát hiện.

Vì vậy, tôi không chắc tại sao máy của bạn không hoạt động, có thể thử đăng App.xml.cs của bạn và bất kỳ mã nào khác mà bạn chưa hiển thị ở đây?

Trong khi đó, tôi nghĩ rằng tôi sẽ chỉ ra một vài điều:

WPF không thực sự xử lý "còn tự do" ngoại lệ một chút khác nhau từ WinForms. Hãy thử nhìn vào này cho một starter:

http://msdn2.microsoft.com/en-us/library/system.windows.application.dispatcherunhandledexception.aspx

Có vẻ như nếu có không phải là một tương đương chính xác trong WPF cho phương pháp SetUnhandledExceptionMode (Xem http://social.msdn.microsoft.com/forums/en-US/wpf/thread/955c75f8-9cd9-4158-bed9-544bd7946413).Hãy thử lời khuyên của họ về việc đăng ký một người xử lý và xem điều đó có giúp bạn không?

Tôi khuyên bạn nên bước qua mã của bạn - đặt điểm ngắt trong Window_Loaded và xem điều gì xảy ra - chú ý cẩn thận đến ngăn xếp cuộc gọi.

Chúc may mắn!

1

Nghiên cứu thêm một chút nữa tôi đã tìm thấy mục nhập blog lạ này mô tả một vấn đề tương tự.

http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/

Vì hóa ra nó có thể là vấn đề kiến ​​trúc vi xử lý 64 bit. Ai có thể đoán được? Nó có thể giải thích tại sao một số người không thể tái tạo vấn đề ví dụ đơn giản của tôi. Tôi đã cố gắng biên dịch ví dụ của tôi trong "Bất kỳ CPU", x64 và x86 nhưng không có kết quả. Trên x64 toàn bộ điều thực sự thổi hoàn toàn rơi với một hộp thoại cửa sổ tai nạn.

Vì vậy, tôi đoán đây là câu trả lời mà không cần xác minh nó trên máy 32 bit.

2

Các "Sao" được giải thích ở đây: http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/

Nói tóm lại, ngoại trừ không thể được nhân giống trong hệ điều hành 64-bit bởi vì có một sự chuyển tiếp giữa người dùng và kernel mode.

Kiểm tra IntPtr.Size trong câu trả lời @midspace không đủ vì IntPtr.Size sẽ bằng 4 trong quy trình x86 chạy trên hệ điều hành x64 (bạn cần sử dụng Environment.Is64BitOperatingSystem thay vì .NET 4 trở lên).

Giải pháp ngay bây giờ: sử dụng một sự kiện khác như ContentRendered được gọi sau Loaded một hoặc đặt mã của bạn trong hàm tạo cửa sổ.

Không bao giờ sử dụng Loaded (hoặc OnLoad trong Winforms), bởi vì nếu có ngoại lệ, bạn không biết điều gì có thể xảy ra.

Bạn cũng có thể xem câu trả lời này: https://stackoverflow.com/a/4934010/200443

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