2010-05-28 19 views
6

Đầu tiên một chút về nền: Tôi có một ứng dụng WPF, là một giao diện đồ họa-front-end cho một ứng dụng Win32 kế thừa. Ứng dụng cũ chạy dưới dạng DLL trong một chuỗi riêng biệt. Các lệnh mà người dùng chọn trong giao diện người dùng được gọi trên "chuỗi kế thừa" đó.Application.Current.Shutdown() so với Application.Current.Dispatcher.BeginInvokeShutdown()

Nếu "chuỗi kế thừa" kết thúc, GUI-front-end không thể làm bất cứ điều gì hữu ích nữa, vì vậy tôi cần phải tắt ứng dụng WPF. Do đó, ở cuối phương thức của luồng, tôi gọi Application.Current.Shutdown().

Vì tôi không nằm trong chuỗi chính, tôi cần gọi lệnh này. Tuy nhiên, sau đó tôi nhận thấy rằng Dispatcher cũng có BeginInvokeShutdown() để tắt máy điều phối. Vì vậy, câu hỏi của tôi là: sự khác biệt giữa cách gọi

Application.Current.Shutdown(); 

và gọi là gì

Application.Current.Dispatcher.BeginInvokeShutdown(); 

Trả lời

7

tôi đã làm một số thử nghiệm nhiều hơn, và bây giờ tôi nghĩ rằng tôi biết sự khác biệt:

1) Như đã trình bày trong trang MSDN, BeginInvokeShutdown, bên cạnh tắt Dispatcher, cũng xóa/hủy bỏ hàng đợi của nó. Shutdown trước tiên xử lý tất cả các mục trong hàng đợi Bộ điều phối.

Sau khi quá trình tắt máy bắt đầu, tất cả các mục công việc đang chờ xử lý trong hàng đợi sẽ bị hủy.

2) Trong một ứng dụng tôi có thể xử lý sự kiện Application.Exit. Sự kiện này được kích hoạt khi tôi gọi tắt máy, nhưng không được kích hoạt khi tôi gọi BeginInvokeShutdown! Điều tương tự cũng áp dụng cho Window.ClosingWindow.Closed.

Đối với điểm tương đồng, trong cả hai trường hợp, luồng chính bị thoát. Tùy thuộc vào các chủ đề đang chạy khác, điều này cũng tắt quá trình: các luồng không phải nền được chạy để hoàn thành trước khi thoát khỏi quá trình.

Dưới đây là mã thử nghiệm của tôi. Bình luận một hoặc các cuộc gọi phương pháp khác trong Application_Startup:

public partial class App 
{ 
    private void Application_Exit(object sender, ExitEventArgs e) 
    { 
     MessageBox.Show("Exiting"); 
    } 

    private void Application_Startup(object sender, StartupEventArgs e) 
    { 
     var testThread = new Thread(
      () => 
      { 
       Thread.Sleep(2000); 
       Application.Current.Dispatcher.BeginInvokeShutdown(System.Windows.Threading.DispatcherPriority.Send); 
       //Application.Current.Dispatcher.BeginInvoke(new Action(() => Application.Current.Shutdown())); 
      }); 
     testThread.Start(); 
    } 
} 

public partial class Window1 
{ 
    public Window1() 
    { 
     this.InitializeComponent(); 

     Dispatcher.BeginInvoke(new Action(() => 
     { 
      Thread.Sleep(1000); 
      Console.WriteLine("One"); 
     })); 

     Dispatcher.BeginInvoke(new Action(() => 
     { 
      Thread.Sleep(1000); 
      Console.WriteLine("Two"); 
     })); 

     Dispatcher.BeginInvoke(new Action(() => 
     { 
      Thread.Sleep(1000); 
      Console.WriteLine("Three"); 
     })); 

     Dispatcher.BeginInvoke(new Action(() => 
     { 
      Thread.Sleep(1000); 
      Console.WriteLine("Four"); 
     })); 
    } 

    private void Window_Closed(object sender, EventArgs e) 
    { 
     Console.WriteLine("Closed"); 
    } 

    private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) 
    { 
     Console.WriteLine("Closing"); 
    } 
} 
1

MSDN page for Shutdown()
MSDN page for BeginInvokeShutdown()

Có vẻ như rằng đây chỉ là một vụ va chạm của thuật ngữ. BeginInvokeShutdown tắt rằng điều phối viên, ứng dụng của bạn có thể về lý thuyết tiếp tục sống sau đó (mặc dù không có người điều phối, nó sẽ khá hạn chế). Shutdown tuy nhiên thực sự thoát khỏi ứng dụng của bạn, đó là những gì bạn muốn.

+0

Vâng, đó chính là câu hỏi không được trả lời trong tài liệu: Việc tắt trình điều phối của ứng dụng cũng tắt ứng dụng? –

+0

Tôi đã xây dựng một ứng dụng thử nghiệm WPF đơn giản cho việc này. Để mô phỏng mã của bạn, tôi đã làm: 'Thread t = new Thread (new ThreadStart (delegate() {Thread.Sleep (50000);})); t.Start(); Application.Current.Dispatcher .BeginInvokeShutdown (System.Windows.Threading.DispatcherPriority.Normal); '. Việc tắt Dispatcher đã giết chết chủ nhân của nó và đóng cửa sổ lại, nhưng đã làm * không * giết chủ đề nền. – JustABill

+0

Hai khác biệt nhỏ: 1) Tôi gọi tắt máy trong chuỗi thứ hai (mặc dù thông qua thử nghiệm tôi có thể thấy rằng nó không có sự khác biệt). 2) Tôi có chuỗi thứ hai được đặt làm chủ đề nền (IsBackground = true). Bằng cách đó, nó cũng bị giết nếu chủ đề chính thoát. –

0

Bằng cách này, Daniel - ứng dụng của chúng tôi được xây dựng trong cùng một cách - WPF front-end đến một ứng dụng Win32 COM (Delphi) chạy riêng biệt. Thật thú vị khi nói và so sánh các phương pháp tiếp cận của chúng tôi.

Nhưng tại sao tôi đã vấp khi câu hỏi của bạn là ứng dụng của chúng tôi được sử dụng để gọi Dispatcher.BeginInvokeShutdown, mà làm việc tốt với ngoại lệ của một vài trường hợp mà nó đã không chấm dứt đúng cách. Khi tôi cuối cùng đã có được bàn tay của tôi trên một máy tính mà trên đó có thể tái sản xuất, chuyển sang Application.Current.Shutdown() đã khắc phục được sự cố. Tôi vẫn không hiểu vấn đề là gì.

+0

Tôi đoán đó là bởi vì các cuộc gọi đến Dispatcher.BeginInvokeShutdown() hủy bỏ/xóa bất kỳ tin nhắn đang chờ xử lý. Trong trường hợp của tôi, tôi cũng làm một loạt các dọn dẹp trong các trường hợp Window.Closing/Closed và Application.Exit (để tắt phần Win32). –

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