2013-03-11 23 views
1

我必须加载一个窗口,并在Window_Loaded我必须加载一些变量并显示在窗口上。后台线程在Window_Loaded事件线程错误

private void Window_Loaded_1(object sender, RoutedEventArgs e) 
{   
    BackgroundWorker worker = new BackgroundWorker(); 

    worker.DoWork += (o, ea) => 
    { 
     try 
     { 
      //code to download some variables which will show on UI of Window Loading 
     } 
     catch (Exception ex) 
     { 
      //The calling thread cannot access this object because a different thread owns it. 
     } 
    }; 

    worker.RunWorkerCompleted += (o, ea) => 
    { 

    }; 

    worker.RunWorkerAsync(); 
} 

但我得到一个线程异常。有没有办法在BackgroundworkerDoWork的窗口上显示变量值?

回答

4

您应该在DoWork部分检索所需的数据,然后将其分配到ea.Result,这将使其在RunWorkerCompleted部分中可用。

RunWorkerCompleted部分,您可以再次访问ea.Result,铸造对象还给你DoWork指定任何类型,并根据需要对你的UI控件应用数据。

worker.DoWork += (o, ea) => 
{ 
    ea.Result = GetMyData(); 
}; 

worker.RunWorkerCompleted += (o, ea) => 
{ 
    var myData = (myDataType)ea.Result; 

    // Assign myData as needed to UI components... 
}; 
+0

我有数百个需要在UI中显示的变量以及DoWork中正在计算的变量。但使用上面的方法我只能在UI上显示一个变量。我对么 ? – 2013-03-12 06:52:11

+2

@АндрейПро使GetMyData()返回一个包含所有必需变量的对象。 – Eirik 2013-03-12 08:17:14

1

您需要让Dispatcher安排您的代码在UI线程上执行并编组必要的参数。尝试是这样的:

Dispatcher.Invoke(
    new Action<string>(() => 
    { 
     // Access UI from here 
    }), 
    DispatcherPriority.Normal 
); 

虽然这个(或这样的事情,因为这是记事本的代码),将解决你的问题,你应该考虑在您的实现使用MVVM模式。然后,您将能够对ViewModel进行更改(只需更新数据),UI将相应更新。

+0

如果您只是使用Invoke,则可以击败使用后台工作者的全部目的。 BGW的目的是只要您使用适当的事件,它就会为您处理编组。 – Servy 2013-03-11 14:05:51

+0

您还通过为WPF使用'BackgroundWorker'来挫败数据绑定和线程池的用途,但是我试图快速解决特定问题,并且如果时间允许要求实现它的人提出更好的建议。 – 2013-03-11 14:09:01

+0

他选择使用BGW,他没有选择使用数据绑定。关于数据绑定,完全不使用某些东西和错误地使用您选择使用的东西是有区别的。关于线程池,不应该使用线程池执行单个长时间运行的操作*。线程池用于大量的短期操作,所以如果他使用线程池,它可能会误用它。 – Servy 2013-03-11 14:21:00