我有一个线程调用一个从Internet获取一些东西的对象。当此对象填满所需的所有信息时,它会引发一个具有对象的事件将所有信息。该事件由启动该线程的控制器使用。
将事件中返回的对象添加到通过View Model方法绑定到GUI的集合中。
问题是我不能将CheckAccess与绑定一起使用...如何解决使用从主要其他线程创建的Object的问题?
将对象添加到主线程集合时收到的错误是:
这种类型的CollectionView不支持从与Dispatcher线程不同的线程更改其SourceCollection。
这是控制器:
public class WebPingerController
{
private IAllQueriesViewModel queriesViewModel;
private PingerConfiguration configuration;
private Pinger ping;
private Thread threadPing;
public WebPingerController(PingerConfiguration configuration, IAllQueriesViewModel queriesViewModel)
{
this.queriesViewModel = queriesViewModel;
this.configuration = configuration;
this.ping = new Pinger(configuration.UrlToPing);
this.ping.EventPingDone += new delPingerDone(ping_EventPingDone);
this.threadPing = new Thread(new ThreadStart(this.ThreadedStart));
}
void ping_EventPingDone(object sender, QueryStatisticInformation info)
{
queriesViewModel.AddQuery(info);//ERROR HAPPEN HERE
}
public void Start()
{
this.threadPing.Start();
}
public void Stop()
{
try
{
this.threadPing.Abort();
}
catch (Exception e)
{
}
}
private void ThreadedStart()
{
while (this.threadPing.IsAlive)
{
this.ping.Ping();
Thread.Sleep(this.configuration.TimeBetweenPing);
}
}
}
答案 0 :(得分:6)
我找到了这个blog的解决方案。
而不是仅仅调用集合来从线程添加对象。
queriesViewModel.AddQuery(info);
我必须将主线程传递给控制器并使用调度程序。警卫的答案非常接近。
public delegate void MethodInvoker();
void ping_EventPingDone(object sender, QueryStatisticInformation info)
{
if (UIThread != null)
{
Dispatcher.FromThread(UIThread).Invoke((MethodInvoker)delegate
{
queriesViewModel.AddQuery(info);
}
, null);
}
else
{
queriesViewModel.AddQuery(info);
}
}
答案 1 :(得分:3)
解决方案是否可以初始化主线程上的对象?
MyObject obj;
this.Dispatcher.Invoke((Action)delegate { obj = new MyObject() });
编辑:在第二次阅读时,这可能不是给定模型的解决方案。您是否收到运行时错误?如果您传回的对象是您自己的对象,确保该对象是线程安全的,可能会使CheckAccess不再需要。