确保异步方法可以更新非线程安全集合的最佳方法是什么?

Esp*_*dbø 2 c# wpf async-await

我正在执行异步调用,最终将更新 GUI 中的集合。异步调用是通过这样的委托命令完成的:

StartDoingUsefulStuffCommand = new DelegateCommand(() => Task.Run(() => StartDoingUsefulStuff()));

public async Task StartDoingUsefulStuff()
{
    try
    {
        await some method
        do something else
        MyCollection.Clear();
        ...
        ...
    }
    catch (Exception e)
    {
       // handle exception
    }
}
Run Code Online (Sandbox Code Playgroud)

最终 StartDoingUsefulStuff 方法想要更新一个集合,导致这个异常,因为另一个线程试图更新一个集合:

PresentationFramework.dll 中发生了“System.NotSupportedException”类型的第一次机会异常

附加信息:这种类型的 CollectionView 不支持从不同于 Dispatcher 线程的线程更改其 SourceCollection。

我找到了一种解决方案:在当前 SynchronizationContext 中运行任务:

Task.Factory.StartNew(() => StartDoingUsefulStuff(), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
Run Code Online (Sandbox Code Playgroud)

这会正常工作,但对我来说,每次从 XAML 调用命令时都执行所有这些操作似乎很乏味。您对我目前的解决方案有何看法/最佳实践是什么?

San*_*esh 5

还有一种更简单的方法可以修复它。在初始化集合的构造函数中,只需在初始化后添加以下行。

BindingOperations.EnableCollectionSynchronization(MyCollection,_lock);哪里_lockprivate static object. 你不必再在你的命令中处理线程安全了。然后就可以await Task.Run安全使用了。