【发布时间】:2014-12-15 17:11:36
【问题描述】:
我有一个异步执行的任务,在此任务的一部分中,通过 Dispatcher.BeginInvoke 在 UI 中添加项目,我在其中更新了 ObservebleCollection。对于对集合的线程安全访问,我使用了 semaphoreSlim,但是随着对 Collection 的请求在 UI 线程中进行,并且 Dispatcher.BeginInvoke 也在 UI 线程中工作,我收到了死锁。
private readonly ObservebleCollection<String> parameters = new ObservebleCollection<String>();
private readonly SemaphoreSlim semaphore = new SemaphoreSlim(0, 1);
//Called from UI
public ObservebleCollection<String> Parameters
{
get
{
semaphore.Wait();
var result = this.parameters;
semaphore.Release();
return result;
}
}
public async Task Operation()
{
await semaphore.WaitAsync();
List<String> stored = new List<String>();
foreach (var parameter in currentRobot.GetParametersProvider().GetParameters())
{
stored.Add(parameter.PropertyName);
}
//Can't do add all items in UI at once, because it's take a long time, and ui started lag
foreach (var model in stored)
{
await UIDispatcher.BeginInvoke(new Action(() =>
{
this.parameters.Add(model);
}), System.Windows.Threading.DispatcherPriority.Background);
}
semaphore.Release();
}
以及我是如何收到死锁的: 当我单击程序中的按钮时,操作执行。 当我单击另一个按钮时,程序尝试访问参数属性。 我收到了一个死锁=D
问题:在异步操作中,我通过 Dispatcher.BeginInvoke 分别为每个项目填充一个 observablecollection,因为如果我使用 Dispatcher 一次添加所有项目,UI 将滞后。所以我需要一个同步方法来访问参数属性,它会等到操作结束。
【问题讨论】:
-
await确保代码将在正确的线程上运行,那么使用 BeginInvoke 有什么意义呢?另外,当所有修改都发生在同一个方法中,在同一个线程中,你为什么要尝试锁定Parameters? -
我无法理解您的代码。您可以用简单的英语更好地解释您要达到的目标。这样会好很多。
-
也不能说我理解代码的作用。我没有看到任何使用异步操作的地方,也没有在后台发生任何事情。您在这里试图解决的真正问题是什么?
-
我使用 Dispatcher 以后台优先级添加项目,因为如果一次添加所有项目,ui 会滞后。
-
你为什么要这样做?为什么你需要使用
Semaphore?您正在更新 UI 元素,它们只能从 UI 线程访问。
标签: c# wpf asynchronous