【问题标题】:WPF thread and GUI how to access object from different thread?WPF线程和GUI如何从不同的线程访问对象?
【发布时间】:2009-08-12 01:54:29
【问题描述】:

我有一个线程调用一个从 Internet 获取一些东西的对象。当此对象填满所需的所有信息时,它会引发一个事件,该对象将包含所有信息。该事件被启动线程的控制器消费。

事件返回的对象随后被添加到通过视图模型方法绑定 GUI 的集合中。

问题是我无法将 CheckAccess 与绑定一起使用...如何解决使用从主线程的其他线程创建的对象的问题?

将对象添加到主线程的集合时收到的错误是:

这种类型的 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);
        }
    }
}

【问题讨论】:

    标签: c# .net wpf


    【解决方案1】:

    我在blog 上找到了解决方案。

    而不是仅仅调用集合从线程中添加对象。

    queriesViewModel.AddQuery(info);
    

    我必须将主线程传递给控制器​​并使用调度程序。 Guard 的答案非常接近。

        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);
            } 
        }
    

    【讨论】:

    • 你能在这个上下文中发布 UIThread 的定义吗?谢谢。不知道在我的代码中用什么代替它
    • 应该是System.Windows.Threading.DispatcherObject的子类。
    【解决方案2】:

    有没有办法在主线程上初始化对象?

    MyObject obj;
    
    this.Dispatcher.Invoke((Action)delegate { obj = new MyObject() });
    

    编辑:在第二次通读时,考虑到您的模型,这可能不是解决方案。您是否收到运行时错误?如果您要传回的对象是您自己的,确保该对象是线程安全的可能会使 CheckAccess 变得不必要。

    【讨论】:

    • 这种类型的 CollectionView 不支持从不同于 Dispatcher 线程的线程更改其 SourceCollection。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多