我有一个公共(public)计时器,在其Tick事件中,我向ViewModel发送了一条消息。我从应用程序中某个位置的按钮启动计时器。问题是,当ViewModel尝试注册(使用MVVM Light)时,存在异常:

“该应用程序调用了已编码为不同线程的接口(interface)。(HRESULT的异常:0x8001010E(RPC_E_WRONG_THREAD))”

这是计时器

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

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

    ...

最佳答案

如果将ObservableCollection绑定(bind)到控件,则只能从UI线程添加或删除值。

为此,您可以使用MVVM Light Toolkit提供的DispatcherHelper类:

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

也可以不使用MVVM Light Toolkit而直接调用调度程序:
Deployment.Current.Dispatcher.BeginInvoke(
    () =>
    {
        foreach (PersonVMWrapper pvmw in action)
        {
            DataSource.Add(pvmw);
        }
    });

10-04 18:34