2010-02-20 44 views
8

Trong một ứng dụng WPF, tôi có một nhiệm vụ truy cập cơ sở dữ liệu được rút gọn, được định kỳ chạy theo bộ đếm thời gian và nhiệm vụ này đã được thực hiện trong một luồng BackgroundWorker.Làm cách nào để xử lý các ngoại lệ từ chuỗi Chủ đề nền?

Khi cố gắng kết nối thất bại, tôi nêu một ngoại lệ bằng cách xây dựng try_catch và tôi muốn cập nhật văn bản Thanh trạng thái trong chuỗi giao diện người dùng.

Có một số cấu trúc sự kiện dựng sẵn trong một BackgroundWorker để triển khai thực hiện điều này, chẳng hạn như DoWorkEventHandler hoặc RunWorkerCompletedEventHandler, có thể được sử dụng cho điều này? Nếu không, làm thế nào để làm điều đó tốt hơn?

Edited (thêm):

Nếu tôi muốn để xử lý các ngoại lệ bên trong RunWorkerCompletedEventHandler, sử dụng e.Error tham số, nó không hoạt động. Trong trường hợp tôi để lại ngoại lệ bị hủy trong chuỗi BackgroundWorker, ứng dụng sẽ treo và các điểm gỡ rối vào chuỗi mã được giải mã bên trong chuỗi BackgroundWorker, nói rằng: Ngoại lệ bị hủy bởi mã người dùng.

Vì vậy, trong trường hợp này, luồng không chỉ dừng lại, báo hiệu cho RunWorkerCompletedEventHandler rằng nó dừng lại với lỗi, nhưng toàn bộ ứng dụng ngừng hoạt động.

+0

Nhờ tất cả để trả lời! Có tính đến một số câu trả lời, tôi đã cập nhật câu hỏi của mình với nhiều chi tiết hơn. – rem

Trả lời

5

Giao diện người dùng WPF có thể được cập nhật từ chuỗi nền bằng cách sử dụng Dispatcher.BeginInvoke.

Ví dụ nếu mã nền của bạn là một phần của một cửa sổ thì bạn có thể cập nhật một TextBlock:

this.Dispatcher.BeginInvoke((Action)(() => 
    { 
     textBlock.Text = "Connection Failed!"; 
    })); 

Edit:

Nếu mã nền của bạn là trong một lớp học khác ngoài cửa sổ của bạn, bạn có thể làm cho một giao diện để giúp:

public interface IShowStatus 
{ 
    void ShowStatus(string message); 
} 

Thực hiện giao diện trong cửa sổ của bạn

public void ShowStatus(string message) 
{ 
    this.Dispatcher.BeginInvoke((Action)(() => 
     { 
      textBlock.Text = message; 
     })); 
} 

Trong lớp học của bạn với nhân viên nền, hãy tạo thuộc tính để giữ tham chiếu đến giao diện.

public IShowStatus StatusDisplay { get; set; } 

Trong lớp Cửa sổ khởi tạo lớp nền.

public void InitBackground() 
{ 
    BackgroundClass background = new BackgroundClass(); 
    background.StatusDisplay = this; 
    ... 

Cuối cùng trong chủ đề nền của bạn, bạn có thể nói:

StatusDisplay.ShowStatus("Connection Failed!"); 
+0

Trong trường hợp của tôi mã nền không phải là một phần của Cửa sổ nhưng nó chạy bên trong một lớp riêng biệt. Hơn nữa, ngoại lệ diễn ra trong một phương thức tĩnh. Vì vậy, từ khóa này không hợp lệ trong trường hợp này. Xin vui lòng, giúp tôi hiểu, làm thế nào tôi có thể tham khảo cửa sổ giao diện người dùng chính của tôi trong trường hợp này? – rem

+0

Tôi đã thêm ghi chú để trả lời câu hỏi của bạn. –

6

RunWorkerCompletedEventArgs e của RunWorkerCompletedEventHandler chứa thuộc tính Error là loại Ngoại lệ. Nếu không có ngoại lệ xảy ra trong quá trình làm việc của chủ đề nền thì prpery có giá trị rỗng. Khác nó chứa lỗi xảy ra.

3
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    Exception exceptionThrowDuringDoWorkEventHandler = e.Error; 
} 
+0

Khi tôi cố gắng ném một ngoại lệ từ chủ đề BackgroundWorker, ứng dụng chỉ gặp sự cố với: Ngoại lệ bị hủy bởi mã người dùng. Tôi không bao giờ nhận được bw_RunWorkerCompleted. Tui bỏ lỡ điều gì vậy? – Doug

3

Đặt WorkerReportsProgress tài sản của người lao động nền để đúng, sau đó thêm một event handler cho sự kiện ProgressChanged.Trong đoạn mã sau, tôi cũng thêm một trình xử lý sự kiện cho Form.Load.

Bây giờ hãy thử đoạn mã sau:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      MessageBox.Show(e.UserState.ToString()); 
     } 

     private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
      try 
      { 
       //some code that throws an exception 
       throw new NotImplementedException(); 
      } 
      catch (Exception ex) 
      { 
       backgroundWorker1.ReportProgress(0/*percent of progress*/, ex); 

      } 
     } 
     private void Form1_Load(object sender, EventArgs e) 
     { 
      backgroundWorker1.RunWorkerAsync(); 
     } 
Các vấn đề liên quan