jas*_*per 5 .net wpf multithreading richtextbox
关于线程,我在RTB和文档生成方面遇到了一些问题.
当TextChanged事件在RTB上触发时,会创建一个新的thead,并将文档生成卸载到此.这可能需要几秒钟,阻塞调用,所以它确实需要在另一个线程上以保持UI响应.
当我尝试将新生成的文档添加到DocumentRTB 的属性时,我遇到的问题是一个例外.(调用线程无法访问此对象,因为另一个线程拥有它.)这不是因为忘记使用Dispatcher.Invoke,因为生成异常的那个,而是因为我在其他线程上创建FlowDocument/Paragraph/Run实例比UI线程(我想??).
有没有办法实现我在这里寻找的东西?
private void rtbQuery_TextChanged(object sender, TextChangedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("Requires update; on thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
backgroundWorker.RunWorkerAsync();
}
private void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
System.Diagnostics.Debug.WriteLine("Generating; on thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
DocumentGenerator dgen = new DocumentGenerator();
string queryText = getQueryText();
e.Result = dgen.GenerateDocument(queryText);
}
private void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("Assigning; on thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);
FlowDocument doc = (FlowDocument)e.Result;
txtQuery.Document = doc; // ! The calling thread cannot access this object because a different thread owns it
}
Run Code Online (Sandbox Code Playgroud)
>Requires update; on thread:9
>Generating; on thread:10
>Assigning; on thread:9
Run Code Online (Sandbox Code Playgroud)
(各种各样的)
所以,正如@Jon Mitchell指出的那样,我无法在UI线程上更新我的RTB,并在另一个线程上创建了一个对象.有一个非常简单的解决方案,需要最少的代码更改,以解决这个问题,并且我发布它以拯救未来的人麻烦.简要说明,在另一个线程上创建一个对象图,然后转换为XAML.然后,UI线程将此XAML转换回对象图,在其自己的线程中,一切正常.
private void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
DocumentGenerator dgen = new DocumentGenerator();
string queryText = getQueryText();
dgen.GenerateDocument(queryText); // start generation
e.Result = dgen; // note, i'm passing the generator, not the document
}
private void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
DocumentGenerator dgen = (DocumentGenerator)e.Result;
txtQuery.Document = dgen.GetFlowDocument();
}
Run Code Online (Sandbox Code Playgroud)
在DocumentGenerator类中
public void GenerateDocument(string data)
{
... // build up the document DOM
// return documentDOM; // used to return the generated item here.
documentXAML = System.Windows.Markup.XamlWriter.Save(documentDOM); // serialize the DOM to XAML
}
public FlowDocument GetDocument()
{
object result = System.Windows.Markup.XamlReader.Parse(documentXAML); // build DOM from XAML
return (FlowDocument)result;
}
Run Code Online (Sandbox Code Playgroud)
我认为问题是因为它FlowDocument是DependencyObject不可冻结的,因此不能在一个线程上创建然后在另一个线程上使用。我认为这是因为当FlowDocument在另一个线程上创建它时,它对于 RTB 有一个不同的调度程序。
可以在AAron 的博客上找到解决方法:
Run Code Online (Sandbox Code Playgroud)FlowDocument doc = new FlowDocument(new Paragraph(new Run("hi"))); System.IO.MemoryStream stream = new System.IO.MemoryStream(); XamlWriter.Save(doc, stream); stream.Position = 0; this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ZeroDelegate)delegate () { flowDoc = (FlowDocument)XamlReader.Load(stream); });
| 归档时间: |
|
| 查看次数: |
1841 次 |
| 最近记录: |