The application called an interface that was marshalled for a different thread when using MVVM light messenger

泄露秘密 提交于 2019-12-24 04:10:06

问题


I have a public timer and in its Tick event I send a message to my ViewModel. I start the timer from a button somewhere in my application. The problem is there is an exception when the ViewModel tries to register (using MVVM Light):

"The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))"

Here is the timer

public static class SomeManager
{
    private static Timer gAppTimer;
    private static object lockObject = new object();

    public static void StartTimer()
    {
        if (gAppTimer == null)
        {
            lock (lockObject)
            {
                if (gAppTimer == null)
                {
                    gAppTimer = new Timer(OnTimerTick, null, 10000, 10000);
                }
            }
        }
    }

    public static void StopTimer()
    {
        if (gAppTimer != null)
        {
            lock (lockObject)
            {
                if (gAppTimer != null)
                {
                    gAppTimer.Change(Timeout.Infinite, Timeout.Infinite);
                    gAppTimer = null;
                }
            }
        }
    }

    private static void OnTimerTick(object state)
    {
        Action();
    }

    public static void Action()
    {
        GlobalDeclarations.GlobalDataSource.Clear();

        Messenger.Default.Send<ObservableCollection<PersonVMWrapper>>(GlobalDeclarations.GlobalDataSource);
    }
}

And here is the ViewModel:

public class PersonVM : INotifyPropertyChanged
{
    ....

    public PersonVM()
    {
        Messenger.Default.Register<ObservableCollection<PersonVMWrapper>>
        (
            this,
            (action) => ReceiveMessage(action)
        );
    }

    private void ReceiveMessage(ObservableCollection<PersonVMWrapper> action)
    {
        foreach (PersonVMWrapper pvmw in action)
        {
            DataSource.Add(pvmw);
        }
    }

    ...

回答1:


If your ObservableCollection is bound to a control, you can add or remove values only from the UI thread.

For this, you can use the DispatcherHelper class provided by the MVVM Light Toolkit:

DispatcherHelper.CheckBeginInvokeOnUI(
    () =>
    {
        foreach (PersonVMWrapper pvmw in action)
        { 
            DataSource.Add(pvmw);
        }
    });

It's also possible to call directly the dispatcher without using the MVVM Light Toolkit:

Deployment.Current.Dispatcher.BeginInvoke(
    () =>
    {
        foreach (PersonVMWrapper pvmw in action)
        { 
            DataSource.Add(pvmw);
        }
    });


来源:https://stackoverflow.com/questions/26848119/the-application-called-an-interface-that-was-marshalled-for-a-different-thread-w

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!