我最近创建了一个辅助方法来限制属性更改事件的速度,以便将数据保存到具有给定延迟的本地数据库。我遇到的唯一问题是该方法显然不是异步运行并阻止我的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
方法,以便它不会阻塞我的主线程呢?
答案 0 :(得分:1)
目前还不清楚你的CreateThrottledCallback
方法究竟做了什么,以及它是否真的是一种真正的异步方法。您可以尝试在if (callback != null)
await Task.Run(() => callback.Invoke());
方法中将其作为后台线程执行:
{{1}}
答案 1 :(得分:0)
由于它与UI无关,因此您可以使用ConfigureAwait(false)
。这将避免捕获当前的同步上下文,任务将在TaskScheduler.Default
线程池上下文中运行。
await callback().ConfigureAwait(false);