2013-04-08 149 views
-5

我嘗試添加加載數據模型並將項目加載到另一個線程上的列表框,因爲將50個項目加載到列表框需要很長時間(大約5秒)。BackgroundWOrker無效的跨線程訪問

我有一個BackgroundWorker的問題,它給我錯誤無效的跨線程訪問我在做什麼錯Inbox.xaml

public Inbox() 
    { 
     InitializeComponent(); 

     DataContext = App.ViewModel; 
    } 

    protected override void OnNavigatedTo(NavigationEventArgs e) 
    { 
     ProgressIndicator progress = new ProgressIndicator 
     { 
      IsVisible = true, 
      IsIndeterminate = true, 
      Text = "Načítání" 
     }; 

     SystemTray.SetProgressIndicator(this, progress); 
     SystemTray.IsVisible = true; 

     BackgroundWorker backgroundWorker = new BackgroundWorker(); 
     backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork); 
     backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted); 

     backgroundWorker.RunWorkerAsync(); 
    } 

    private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     LoadData(); 
    } 

    void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     if (e.Error != null) 
     { 
      MessageBox.Show(e.Error.Message); 
     } 
     else 
     { 
      SystemTray.IsVisible = false; 
     } 
    } 

    private void LoadData() 
    { 
     try 
     { 
      (this.DataContext as MainViewModel).LoadInboxData(); 
     } 
     finally 
     { 
      TasksListBox.ItemsSource = (this.DataContext as MainViewModel).Tasks; 
     } 
    } 

他是代碼?

+0

你得到什麼錯誤?你可以發佈堆棧跟蹤嗎? – Shark 2013-04-08 14:09:18

+0

當它訪問UI控件的ItemsSource時,會猜測它是你的'LoadData'。你需要調用'Dispatcher'上的調用,我認爲,儘管我記不清楚了。 – 2013-04-08 14:11:29

+2

您可以在這裏和其他網站上搜索成千上萬個有關此問題的其中一個。這是一個每天要問幾次的問題......只要看看屏幕側面的'Related'線程即可。 – Servy 2013-04-08 14:12:51

回答

1

您正試圖從非UI線程更新UI,因此您會收到異常。

只有UI線程可以執行UI更新,您需要使用Dispatcher以便從非UI線程更新UI。

Dispatcher.BeginInvoke(() => 
{ 
    // Update UI in here as this part will run on the UI thread. 
}); 

參見:http://msdn.microsoft.com/en-gb/library/system.windows.threading.dispatcher.begininvoke.aspx

+1

使用後臺工作人員的要點是,您不需要手動調用。他應該簡單地使用工作完成事件中的結果更新UI,而不是執行工作事件。 – Servy 2013-04-08 14:12:26

+0

確定它的工作原理,但我需要顯示加載時,項目添加到列表框,這是什麼需要很長的時間 – Earlgray 2013-04-08 14:45:22

+0

@Servy他確實可以!那將是這樣做的一種方式,但是,如果他需要在長時間運行的操作系統之間更新UI,那麼調度呼叫就是一種方式,除非他創建了幾個後臺工作人員並將它們連在一起 - 凌亂!一個更好的「現代」方法是簡單地交給schmancy新的異步方法,讓異步等待長操作被強制到新線程處理所有的鏈接和繁重工作。 – Clint 2014-05-15 09:24:54

2

BackgroundWorker.DoWork處理程序在後臺非UI線程中運行。在你的例子中,LoadData()方法在後臺非ui線程上運行,並且你在該方法中設置ListBox的ItemSource屬性。

您應該嘗試將該代碼移至BackgroundWorkder.RunWorkerCompleted處理程序,因爲此處理程序在UI線程上運行。

您的代碼可以被重新寫的下方,以避免錯誤:

void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    if (e.Error != null) 
    { 
     MessageBox.Show(e.Error.Message); 
    } 
    else 
    { 
     SystemTray.IsVisible = false; 
    TasksListBox.ItemsSource = (this.DataContext as MainViewModel).Tasks; 
    } 
} 

private void LoadData() 
{ 
    (this.DataContext as MainViewModel).LoadInboxData(); 
} 
+0

當我從代碼中移除loadinboxdata()行並且當項目添加到列表框時需要顯示加載時,我也有同樣的錯誤,這是需要很長時間的 – Earlgray 2013-04-08 14:30:27

+0

如果您正在尋找覆蓋「加載」橫幅,則有多種方法可以實現 1)有另一個控件,例如邊框/文本塊/進度條,然後按順序將它顯示在ListBox的頂部,並根據需要切換該控件的可見性。 2)用戶裝飾者控制。參考這個http://www.codeproject.com/Articles/57984/WPF-Loading-Wait-Adorner – sthotakura 2013-04-08 15:03:27

相關問題