简体   繁体   English

WPF线程和GUI如何从不同的线程访问对象?

[英]WPF thread and GUI how to access object from different thread?

I have a thread that call an object that get some stuff from Internet. 我有一个线程调用一个从Internet获取一些东西的对象。 When this object is filled up with all information required, it raises an event with an object will all the information. 当此对象填满所需的所有信息时,它会引发一个具有对象的事件将所有信息。 The event is consumed by the controller that has started the thread. 该事件由启动该线程的控制器使用。

The returned object from the event is than added into a collection that is binded the the GUI via a View Model approach. 然后将事件中返回的对象添加到通过View Model方法绑定到GUI的集合中。

The problem is that I can't use the CheckAccess with the binding... how can I fix the problem of using Object that has been created from an other thread of the main one? 问题是我不能将CheckAccess与绑定一起使用...如何解决使用从主要的其他线程创建的Object的问题?

The error that I receive when I add the object to the collection of the main thread is : 我将对象添加到主线程集合时收到的错误是:

This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread. 这种类型的CollectionView不支持从与Dispatcher线程不同的线程更改其SourceCollection。

This the the controller: 这个控制器:

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

I found the solution over this blog . 我在这个博客上找到了解决方案。

Instead of just calling the collection to add the object from the thread. 而不是只是调用集合来从线程添加对象。

queriesViewModel.AddQuery(info);

I have to pass the main thread to the controller and use the dispatcher. 我必须将主线程传递给控制器​​并使用调度程序。 Guard answer's was very close. 警卫的答案非常接近。

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

Could a solution be to initialize the object on the main thread? 解决方案是初始化主线程上的对象吗?

MyObject obj;

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

Edit : At a second read-through, this probably isn't a solution given your model. 编辑 :在第二次阅读时,这可能不是给定模型的解决方案。 Are you receiving a runtime error as it is? 您是否收到运行时错误? If the object you're passing back is your own, ensuring the object is thread-safe could make CheckAccess unneccessary. 如果您传回的对象是您自己的对象,确保该对象是线程安全的,可能会使CheckAccess不再需要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM