用于 ViewModel 更新的 TimerEvent 中的跨线程访问无效 [英] Invalid cross-thread access in TimerEvent for ViewModel update

查看:25
本文介绍了用于 ViewModel 更新的 TimerEvent 中的跨线程访问无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有 Load() 方法的 ViewModel (ObservableCollection).在我的用户界面中,我有一个调用 Load()-Method 的重新加载"按钮.到这里一切都很好.

I have a ViewModel (ObservableCollection) with a Load()-Method. In my UI I have a "Reload"-Button that calls the Load()-Method. Till here everything is fine.

ViewModel 在 App.xaml.cs 中声明,因此可全局访问.

The ViewModel is declared in App.xaml.cs so it´s globally accessible.

现在我想独立于用户交互更新 ViewModel.我创建了一个计时器,如下所示:

Now I want to update the ViewModel independent of user interaction. I created a Timer as follows:

public static class WhagooBackgroundManager
{
    private static bool _isInitialized = false;
    private static bool _isRunning = false;
    private static Timer _AppTimer;
    private static int _runcounter = 0;
    private static DateTime _lastRun = DateTime.MinValue;

    public static void Initialize(int pIntervall)
    {
        if (_isInitialized == false)
        {
            _isInitialized = true;
            // Init the timer - it will call OnTimerTick every "pIntervall" secods, passing null as argument to the method.
            _AppTimer = new Timer(OnTimerTick, null, pIntervall * 1000, pIntervall * 1000);
        }
    }

    private static void OnTimerTick(object state)
    {
        _runcounter = _runcounter + 1;
        // Exit if still running:
        if (_isRunning == true)
        {
            _currentstatus = "Skipped Execution, still running";
            return;
        }
        // Executing Main-Routine:
        GetLocation();
        _lastRun = DateTime.UtcNow;
    }

    private static async void GetLocation()
    {
        _isRunning = true;
        // Viewmodels updaten:
        await App.ViewSuggestionsData.LoadData();
        }
        _isRunning = false;
    }
}

当计时器运行时,我收到一个错误:无效的跨线程访问.寻找可能的解决方案,我发现,我必须invoke.我该怎么做.如果我这样做,如何避免用户在计时器运行时按下更新"按钮?

When Timer runs, I get an Error: Invalid cross-thread Access. Searching for possible Solutions I found out, that I have to invoke. How do I do this exactly. And if I do this, how can I avoid that a user is pressing the "Update"-Button while Timer is running?

更新:

这不起作用:

Deployment.Current.Dispatcher.BeginInvoke( () => { 
    await App.ViewSuggestionsData.LoadData();
});

我不能在那里使用 await,但我必须在里面调用 Web Api.

I can´t use await there, but I must because of calling Web Api inside.

推荐答案

有很多方法可以解决这个问题.根据评论,最简单的方法是使用 Dispatcher 更新 UI 线程上的 ObservableCollection.

Lots of ways to solve this. Based on the comments the simplest way would be updating the ObservableCollection on the UI thread using the Dispatcher.

async Task LoadData()
{
    // do some stuff
    var data = await SomeWebCall();
    Deployment.Current.Dispatcher.BeginInvoke( () => {
        MyObservableCollection = data; // or new ObservableCollection(data);
    });
}

这篇关于用于 ViewModel 更新的 TimerEvent 中的跨线程访问无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆