【发布时间】:2013-02-18 00:37:31
【问题描述】:
我正在尝试生成和分派(同时让我的 UI 线程使用progressRing.IsActive = true;),三个List 对象位于BackgroundWorker 上,然后将所述列表传输到UI Thread,但我遇到了问题...
Must create DependencySource on same Thread as the DependencyObject.
资源,我已阅读
- C# lock (MSDN Documentation)
- Sending Arguments to Background Worker (Stackoverflow)
- C# Background Worker (MSDN Documentation)
- C# getting Background Worker to return a result (Stackoverflow)
部分类MainWindow的方法BackgroundLogin()
private void BackgroundLogin()
{
//process the form on UI Thread
this.LoginForm(FadeOut);
this.LoadingRing(FadeIn);
//Start a new Thread
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
//initialize custom class WorkerThread object to store/process a result
WorkerThread wt = new WorkerThread(this, txtEmailAddress.Text, txtPassword.Password);
//start the worker and send the object across.
worker.RunWorkerAsync(wt);
}
部分类MainWindow的方法worker_DoWork
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
//grab the object
WorkerThread wt = (WorkerThread)e.Argument;
//check if we can login
if (!wt.Login())
{
//cancel the thread
e.Cancel = true;
}
else
{
//load additional data
wt.UpdateAuthLbl(".. Loading New Data ..");
wt.LoadLists();
wt.UpdateAuthLbl(".. Data Loaded ..");
}
//pass the object back
e.Result = wt;
}
类WorkerThread的方法loadLists()
/// <summary>
/// Load data into the list
/// </summary>
public void LoadLists()
{
this.gene_fact_list = db.loadGeneFactTable();
this.gene_trait_fact_list = db.loadGeneTraitFactTable(this.gene_fact_list);
this.category_trait_list = db.loadCategoryTraits();
}
部分类MainWindow的方法worker_RunWorkerCompleted,类GeneList的对象gl
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//grab the finished object
WorkerThread wt = (WorkerThread) e.Result;
//work out if we are logged in
Boolean LoginFlag = !e.Cancelled && e.Error == null;
if (LoginFlag)
{
lblAuthentication.Content = ".. Loading Interface ..";
//pass the finished object into memory
this.gl = wt;
//reset the listbox
this.resetListBox();
}
this.LoginForm(LoginFlag);
}
方法resetListBox()和ListBoxItems
/// <summary>
/// Load the data for the form
/// </summary>
public void resetListBox()
{
if (this.gl.notNullOrEmpty())
{
this.ListBoxItems.Clear();
//begin compiling the mainTab
foreach (KeyValuePair<long, GeneNotesDataModel> kvp in this.gl.gene_fact_list)
{
this.ListBoxItems.Add(kvp.Value);
}
}
} //close function
//declare WPF list binding
private ObservableCollection<GeneNotesDataModel> _listBoxItems = new ObservableCollection<GeneNotesDataModel>();
/// <summary>
/// Control the listbox of rsid codes
/// </summary>
public ObservableCollection<GeneNotesDataModel> ListBoxItems
{
get { return _listBoxItems; }
set { _listBoxItems = value; }
}
XAMLListBoxlstSnpCodes
<ListBox ItemsSource="{Binding ElementName=UI, Path=ListBoxItems}" Margin="6,38,0,60" BorderThickness="2" HorizontalAlignment="Left" Width="180" Name="lstSnpCodes" SelectionChanged="lstSnpCodes_SelectionChanged" KeyUp="OnKeyUpHandler" />
this.ListBoxItems.Add(kvp.Value); 行导致Exception 发生(如果我用Debug.WriteLine(kvp.Value.getValueAsString()); 替换它,它将运行得很好)。关于为什么我得到一个 DependencySource 异常的任何想法?为什么不能将ListA 从Slave Thread 转移到Main Thread?
PasteBin 链接将于 2013 年 4 月到期
【问题讨论】:
-
gene_fact_list 是属性还是暴露字段?如果它是一个属性,则只能在主线程 (AFAIK) 上执行此操作。也许您需要的是访问器方法(例如 Set_gene_fact_list(list lst)。
-
另外,请记住使用互斥锁或某种只读对象来锁定目的,以将读/写操作同步到列表。
-
@William 所有三个列表都是
MainWindow.xaml(或MainWindow window)的属性,我尝试过使用Setter,但我遇到了同样的问题。所以当前的sn-p是使用{get;set;}更新window中的列表。 -
@William 你能补充一个答案吗? (最好有关于Task 的详细信息,我希望通过
Task访问db方法)
标签: c# wpf multithreading dependencies backgroundworker