2012-03-12 58 views
1

我有一个线程在wpf中生成GUI元素。画布是有绘制对象(矩形等...)Task.Factory和线程之间的通信

WPF线程调用另一个线程让我们命名它的计算线程。该线程计算要在画布中显示的元素的大小和位置等。

我想让这两部分(GUI和计算)在不同的线程中运行。 “计算线程”基于一个没有引用wpf功能的库。

现在我想显示由wpf线程显示的计算线程的中间数据。 我做这样的说法:

的计算线程触发一个事件(DataReady)由WPF的线程来实现:

void MyRegStringObject_DataReady() 
{ 
    if (DebugMode) 
    MyDrawingBoard.DrawRegElements(); 
} 

现在的问题是,这将引发错误: “调用线程不能访问这个对象,因为不同的线程拥有它”

这里有一些在stackoverflow引用这个错误的回答问题,但没有一个可以帮助我的情况。

功能DrawRegElements()要清除画布对象(除其他事项外):

curCanvas.Children.Clear(); 

在在引发错误的代码这个位置。 似乎由calc-thread触发的函数MyRegStringObject_DataReady也被calc-thread所支付。但是在类中定义了wpf-thread基于。

我该如何解决这个问题?有人有什么主意吗? 顺便说一句: 的钙线程称为是这样的:

CalcElements = Task.Factory.StartNew<bool>(MyRegStringObject.CalcRegElements); 

当线程完成我定义:

CalcElements.ContinueWith((FinishCalcRegElements) => 
{ 
    MyDrawingBoard.DrawRegElements(); 
}, CancellationToken.None, TaskContinuationOptions.None, 
TaskScheduler.FromCurrentSynchronizationContext()); 

没有异议。 Everythins运行完美。 ContinueWith中定义的函数似乎由wpf-thread所支持。

回答

2

错误消息很简单,您正试图从现在拥有的线程访问UI元素。委派这项工作,WPF调度员,其与主UI线程相关联,这将发布从辅助线程的所有消息UI线程:

Application.Current.Dispatcher.BeginInvoke((ThreadStart)delegate 
    {    
     MyDrawingBoard.DrawRegElements(); 
    }); 

为确保您使用的是正确的调度,与主UI线程相关联,您可以将它作为参数传递给工作线程代码,因此只需从主UI线程传递Dispatcher.Current,否则在辅助线程中调用Dispatcher.CurrentDispatcher将初始化与调用工作线程关联的新实例。或者只是使用Application.Current.Dispatcher,它会引用主UI线程的分派器。

PS:

但它是在类中定义的WPF线程是基于

这是错误的假设,类本身不相关的任何线索。 Concrtete类实例是。因此,您可以在UI或工作线程中创建UI /非UI相关的类。

同样重要的点在哪个线程DataReady事件已经被解雇?

+0

当你说'Dispatcher.Current'你的意思是[Dispatcher.CurrentDispatcher](http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.currentdispatcher.aspx),对不对?我猜想MyDrawingBoard是某种WPF控件,所以'MyDrawingBoard.Dispatcher.BeginInvoke'就可以。 – Clemens 2012-03-12 10:52:19

+0

右'CurrentDispatcher',已修复。你试过这个吗? – sll 2012-03-12 10:58:24

+0

@ sll Dispatcher.CurrentDispatcher.BeginInvoke并没有真正的工作我不知道为什么,但UI线程接收到工作线程触发的事件,但DrawRegElements没有被调用。它只在最后被调用(当工作线程完成时)。 – manton 2012-03-12 11:05:41