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

时间:2022-12-17 21:02:02

I have a thread that call an object that get some stuff from 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.

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

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

2 个解决方案

#1


6  

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

#2


3  

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不再需要。

#1


6  

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

#2


3  

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不再需要。