2011-06-21 33 views
5

我將項目從winforms轉移到WPF。當我的代碼基於WinForms我使用(this.InvokeRequired)來檢查線程是否有訪問權限。現在我使用基於我的Mainform的以下代碼:來自後臺工作者的UI訪問問題

// this is the delegate declaration to Allow Background worker thread to write to Log Output 
    delegate void LogUpdateCallBack(String LogMessage); 

    // method to update the Log Window from the Background Thread 
    public void LogUpdate(String LogMessage) 
    { 
     Console.WriteLine("Entering"); 
     if (!Application.Current.Dispatcher.CheckAccess()) 
     { 
      Console.WriteLine("Thread doesn't have UI access"); 
      LogUpdateCallBack callback = new LogUpdateCallBack(LogUpdate); 
      Application.Current.Dispatcher.Invoke(callback, LogMessage); 
     } 
     else 
     { 
      Console.WriteLine("Thread has UI access"); 
      listBox_Output.Items.Add(LogMessage); 
      Console.WriteLine(LogMessage); 
      // listBox_Output.TopIndex = listBox_Output.Items.Count - 1; 
     } 
     Console.WriteLine("Exiting"); 
    } 

我遇到的問題是Listbox未更新。沒有錯誤或異常,我嘗試更新其他UI控件。 LogMessage正在寫入輸出窗口,所以我難倒了。

這裏的樣本控制檯輸出:

Entering 
Thread doesn't have UI access 
Entering 
Thread has UI access 
My LogMessage is output here 
Exiting 
Exiting 
Entering 
Thread doesn't have UI access 
Entering 
Thread has UI access 
My LogMessage is output here 
Exiting 
Exiting 

我試着更新其他UI控件只是爲了檢查是否與我的列表框,但沒有運氣的問題。

除了切換到CheckAccess(),我在新的WPF代碼中唯一的其他主要更改是將所有在後臺工作中運行的代碼都放在另一個類中。我不確定這是否可以成爲問題的一部分?

-

@JonRaynor

我想你的想法:

Application.Current.Dispatcher.BeginInvoke(new LogUpdateCallBack(LogUpdate), LogMessage) 

但是我的列表框仍然沒有更新,如果我輸出

Console.WriteLine(listBox_Output); 

我看到名單盒式陣列增長:

System.Windows.Controls.ListBox Items.Count:2020 
System.Windows.Controls.ListBox Items.Count:2021 
System.Windows.Controls.ListBox Items.Count:2022 
System.Windows.Controls.ListBox Items.Count:2023 
System.Windows.Controls.ListBox Items.Count:2024 
System.Windows.Controls.ListBox Items.Count:2025 

但形式沒有改變。這很混亂!

+0

上列表框的任何數據綁定? Page_Load事件中的Items.Add(「test」)是否有效? –

+0

沒有DataBinding ..我正在從我的代碼的其他區域更新列表框,沒有任何困難。我也嘗試更新其他用戶界面控件,以防止出現Listbox問題..沒有運氣。 – mrbencowell

+0

另一個奇怪的事情要注意的是,如果我在控制檯輸出listBox_Output我可以看到項目正在添加(它報告項目數),所以它似乎是我的項目被添加,但用戶界面不是完全更新。我試過listBox_Output.InvalidateVisual();沒有效果。 – mrbencowell

回答

1

我終於解決了這個問題。

我的問題是,當我從另一個線程和另一個類調用LogUpdate方法時,因此我需要將包含列表框的主窗體的引用傳遞到此類中,而不是創建主實例在中學階段形成。

所以而非具有此聲明在我的次級類:

public MainWindow MainForm = new MainWindow(); 

我需要以下形式的引用傳遞到在二次類中的方法:

public void Plot(BackgroundWorker worker, MainWindow MainForm) 
2

我剛剛開始使用WPF,不得不重新學習舊的WinForms方法。我一直在使用的BeginInvoke()和這種類型的我的屏幕(形式)語法...

public delegate void WorkCompleted(); 

     /// <summary> 
     /// Marks the end of the progress 
     /// </summary> 
     private void ProgressComplete() 
     { 
      if (!this.Dispatcher.CheckAccess()) 
      { 
       this.Dispatcher.BeginInvoke(new WorkCompleted(ProgressComplete), System.Windows.Threading.DispatcherPriority.Normal, null); 
      } 
      else 
      { 
       this.buttonClose.Visibility = Visibility.Visible; 
       this.progressBarStatus.IsIndeterminate = false; 
      } 
     } 
+0

謝謝你的建議..我會嘗試這種方法,看看我是否得到任何地方。 – mrbencowell

0

在WPF中,所有的UI控件自DispatcherObject的。這意味着你的ListBox控件本身就是一個可以調度的對象。嘗試調用該對象上的Dispatcher而不是依賴表單本身。取出委託上的參數(因爲您可以訪問LogMessage變量),它看起來像這樣:

public void LogUpdate(string LogMessage) 
{ 
    Console.WriteLine("Entering"); 
    if (listBox_Output.Dispatcher.CheckAccess()) 
    { 
     listBox_Output.Dispatcher.Invoke(new LogUpdateCallBack(delegate 
     { 
      listBox_Output.Items.Add(LogMessage); 
     })); 
     Console.WriteLine(LogMessage); 
    } 
} 
+0

感謝您的建議,但是,這個問題是因爲我誤解了在另一個類中聲明MainForm的一個實例,我認爲這會讓我訪問mainform,但它只是創建了一個新的實例。所以當我更新控件我沒有看到結果。 – mrbencowell