I have a code like this:
private static var Locker = new Object();
private void SensitiveCode()
{
lock (Locker)
{
SomeCodeSensitive(); .....
Dispatcher.BeginInvoke(new Action(() =>
{
SomeCodeThatUpdatesUI();
}));
MoreCodeSensitive();
}
}
Also i have a thread running doing something like this:
while (X)
{
SensitiveCode();
Thread.Sleep(5000);
}
Now in my main thread I sometimes call SensitiveCode(); SensitiveCode() is on lock because it must not be called from 2 threads at same time.
Well, the problem is I don't know why, sometimes i find a deadlock, sometimes on UI (the UI freezes), sometimes on thread. I don't know what is happening, one of the threads stops in lock() cause it is supposed that variable "Locker" is in use for the other thread, but that is not true. I think that the problem could be the BeginInvoke inside the lock, but I think that should not be enough to lock this code.
Also, it is very hard to reproduce the problem, I've been testing for 3 hours and it has appeared only 2 times.
Does someone know what could it be?
Thanks!
Update Due to questions:
SensitiveCode() is doing work with some AsyncObservableCollection objects (class from http://www.thomaslevesque.com/2009/04/17/wpf-binding-to-an-asynchronous-collection/) .
Doing things like reading from database and filling those AsyncObservableCollection(). I lock this action because I cannot allow the thread updates my AsyncObservableCollection while the user does it at the same time.
Also, the UI does this
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;
}));
Update 2:
After doing again, here is a screenshot of the threads when the deadlock ocurred
https://i.stack.imgur.com/BjoEp.png
MovePageForward is the action I do on the UI, it contains this code:
public static void MakePageForward()
{
lock (ConfigParameters.Lock)
{
_currentPage++;
ShowTablesInWindow();
}
}
TimerConnectionTick has the following code:
private static void TimerConnectionTick()
{
while (!_thisDisposing)
{
ShowTablesInWindow();
if (!_thisDisposing)
Thread.Sleep(5000);
}
}