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.
The returned object from the event is than added into a collection that is binded the the GUI via a View Model approach.
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?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With