3 回答
TA贡献1848条经验 获得超10个赞
是否有处理此类问题的良好做法?
如果您希望两个保存都发生,那么使用锁(或SemaphoreSlim
)对它们进行序列化是一种方法。如果您想阻止第二次保存开始,那么通常的方法是在保存过程中禁用这些控件,例如,通过IsBusy
数据绑定到您的 UI 的属性。
注意事项:
IsBusy
同步设置您的属性。这会立即禁用控件。IsBusy
在 a中取消finally
设置,以确保它始终未设置,即使发生错误也是如此。
TA贡献1804条经验 获得超7个赞
正如您所说,我还认为锁是最好的方法。
我推荐使用 Stepehen Cleary straigthforward 解决方案:https ://github.com/StephenCleary/AsyncEx
因此,您的代码看起来像
private readonly AsyncLock _lock = new AsyncLock();
private async void Save()
{
var id = Guid.NewGuid();
using (await _lock.LockAsync())
{
// It's safe to await while the lock is held
Debug.WriteLine($"Starting save {id}");
await Task.Delay(100); // Simulate slow task
Debug.WriteLine($"Finished save {id}");
}
}
这并不会真正影响代码的可读性,并且您最终会得到一个异步方法队列。
TA贡献1825条经验 获得超4个赞
这是 Rx 的绝佳样本。如果你不想使用ReactiveUI(它可以很容易地与 MVVMLight 相邻),你所需要的只是一个属性改变的信号。
使用 RxUI:
this.WhenAnyValue(x => x.MyText, x => x.IsChecked) // this you will need to emulate if you don't want RxUI
.Throttle(TimeSpan.FromMilliseconds(150)) // wait for 150ms after last signal, if there isn't any, send your own further into pipeline
.Synchronize()
.Do(async _ => await Save()) // we have to await so that Synchronize can work
.Subscribe();
这将在最后一次 MyText 更改或 IsChecked 更改后等待 150 毫秒,然后执行一次保存。
此外,RxUI 有非常聪明的 ICommand 实现,它支持开箱即用的异步工作,包括在工作期间禁用命令。
- 3 回答
- 0 关注
- 115 浏览
添加回答
举报