阻止UI线程的方法

时间:2018-06-08 19:02:05

标签: c# wpf multithreading mvvm callback

我最近创建了一个辅助方法来限制属性更改事件的速度,以便将数据保存到具有给定延迟的本地数据库。我遇到的唯一问题是该方法显然不是异步运行并阻止我的UI线程。

为了对其进行测试,我已将该事件附加到SettingsViewModel PercentageSliderViewModel

public class SettingsViewModel : BaseVM
{
    public PercentageSliderViewModel Activity { get; set; }

    [...]

    public SettingsViewModel() {
        Activity.PropertyChanged += CreateThrottledCallback(Save, 1000);
    }

    [...]

    public async Task Save()
    {
        // Save data
    }
}

这是我的助手方法:

public PropertyChangedEventHandler CreateThrottledCallback(
            Func<Task> callback, int throttle = 1000)
{
    bool throttling = false;
    bool callFinal = false;

    return async(s, e) =>
    {
        if (throttling)
        {
            callFinal = true;
            return;
        }

        throttling = true;

        await callback?.Invoke();

        await Task.Delay(throttle).ContinueWith(_ => throttling = false);

        if (callFinal)
        {
            await callback?.Invoke().ContinueWith(_ => callFinal = false);
        }
    };
}

即使节流工作正常,当我从左向右移动滑块并发生回调时,它会在一段时间内“冻结”。

调试显示它正在UI线程上运行。

如何异步运行CreateThrottledCallback方法,以便它不会阻塞我的主线程呢?

2 个答案:

答案 0 :(得分:1)

目前还不清楚你的CreateThrottledCallback方法究竟做了什么,以及它是否真的是一种真正的异步方法。您可以尝试在if (callback != null) await Task.Run(() => callback.Invoke()); 方法中将其作为后台线程执行:

{{1}}

答案 1 :(得分:0)

由于它与UI无关,因此您可以使用ConfigureAwait(false)。这将避免捕获当前的同步上下文,任务将在TaskScheduler.Default线程池上下文中运行。

await callback().ConfigureAwait(false);