我有这样的代码:
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);
}
}
答案 0 :(得分:0)
如果没有看到所有代码,就很难调试。您的SomeCodeThatUpdatesUI()方法中的某个位置是否也可能触发对Locker的锁定?如果你以递归方式触发锁定它会毫无问题地通过,但是如果你在Dispatcher线程的BeginInvoke中这样做(这可能与你提到的当前线程不同,你从不同的线程调用它),它会锁定并造成死锁。
如果是这种情况,也许您可以在需要锁定时进行重构,或使用类似ReaderWriterLockSlim(https://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim(v=vs.110).aspx)
的内容