【发布时间】:2017-03-10 16:01:47
【问题描述】:
我有这样的代码:
private static var Locker = new Object();
private void SensitiveCode()
{
lock (Locker)
{
SomeCodeSensitive(); .....
Dispatcher.BeginInvoke(new Action(() =>
{
SomeCodeThatUpdatesUI();
}));
MoreCodeSensitive();
}
}
我也有一个线程正在运行,做这样的事情:
while (X)
{
SensitiveCode();
Thread.Sleep(5000);
}
现在在我的主线程中,我有时会调用 SensitiveCode(); SensitiveCode() 处于锁定状态,因为不能同时从 2 个线程调用它。
嗯,问题是我不知道为什么,有时我发现死锁,有时在 UI 上(UI 冻结),有时在线程上。我不知道发生了什么,其中一个线程在 lock() 中停止,因为假设变量“Locker”正在用于另一个线程,但事实并非如此。我认为问题可能是锁内的 BeginInvoke,但我认为这不足以锁定此代码。
另外,这个问题很难重现,我测试了3个小时,只出现了2次。
有人知道它是什么吗?
谢谢!
更新由于问题:
SensitiveCode() 正在处理一些 AsyncObservableCollection 对象(来自http://www.thomaslevesque.com/2009/04/17/wpf-binding-to-an-asynchronous-collection/ 的类)。
做一些事情,比如从数据库中读取并填充那些 AsyncObservableCollection()。我锁定此操作是因为我不能允许线程在用户同时更新我的 AsyncObservableCollection 时更新它。
另外,用户界面也会这样做
Dispatcher.BeginInvoke(new Action(() =>
{
if (tables.Count != TablesInWindow.Count)
TablesInWindow.ClearAndAddRange(tables);
else
{
if (tables.Where((t, i) => !TablesInWindow[i].Equals(t)).Any())
TablesInWindow.ClearAndAddRange(tables);
}
ButtonPageBack.IsEnabled = canGoBack;
ButtonPageNext.IsEnabled = canGoFoward;
}));
更新 2:
再做一次,这里是死锁发生时的线程截图
http://i.imgur.com/8xyIy6h.png
MovePageForward 是我在 UI 上执行的操作,它包含以下代码:
public static void MakePageForward()
{
lock (ConfigParameters.Lock)
{
_currentPage++;
ShowTablesInWindow();
}
}
TimerConnectionTick 代码如下:
private static void TimerConnectionTick()
{
while (!_thisDisposing)
{
ShowTablesInWindow();
if (!_thisDisposing)
Thread.Sleep(5000);
}
}
【问题讨论】:
-
你是在使用你没有使用 Dispatcher.Invoke 还是在调用堆栈下方的某个地方锁定(在 SomeCodeSensitive 或 MoreCodeSensitive 部分)?
-
您能否为您的示例添加更多上下文,以便重现该问题。
lock和thread.Sleep都会阻塞任何试图进入的线程,再次需要更多上下文。一些奇怪的事情:Dispatcher不是敏感代码 为什么会被锁定?而Locker不是敏感物体,为什么要用它来做锁,在锁块内有多少敏感物体被触动了? -
None Dispatcher.Invoke SensitiveCode 中的代码。
-
嗯...这不是敏感代码,我可以将其从锁中取出,但我不知道为什么它会有所帮助。无论如何,我的问题是我无法重现此问题。我在5小时的测试中发生了3次,真是令人头疼。我会尝试拿出 BeginInvoke 代码并将其发送给客户,以便他们在真实环境中对其进行测试,因为我不知道还能做什么......储物柜是我用来锁定的对象,它不敏感只是一个新的对象()。我在敏感代码中触及的是对数据库的调用和更新 AsyncObservableCollection 对象。
标签: c# wpf multithreading locking