У меня есть LongOperationHelper, который я активирую при каждой потенциально длительной операции.
Он отображает полупрозрачный слой и не позволяет щелкать мышью до тех пор, пока операция не закончится, и вращающийся элемент управления отображает ход выполнения.
Это выглядит примерно так (не хватает бизнес-логики, но идея ясна, я думаю):
Отредактировано: (Добавлен недостающий код общих состояний, которые фактически нуждались в блокировке - это больше похоже на проблемный код)
(Мое решение выложено в ответе ниже)
public static class LongOperationHelper
{
private static object _synchObject = new object();
private static Dictionary<string, int> _calls = new Dictionary<string, int>();
private static Action<string> DisplayLongOperationRequested;
private static Action<string> StopLongOperationRequested;
public static void Begin(string messageKey)
{
lock (_synchObject)
{
if (_calls.ContainsKey(messageKey))
{
_calls[messageKey]++;
}
else
{
_calls.Add(messageKey, 1);
DispatcherHelper.InvokeIfNecesary(() =>
{
//Raise event for the MainViewModel to display the long operation layer
DisplayLongOperationRequested?.Invoke(messageKey);
});
}
}
}
public static void End(string messageKey)
{
lock (_synchObject)
{
if (_calls.ContainsKey(messageKey))
{
if (_calls[messageKey] > 1)
{
_calls[messageKey]--;
}
else
{
_calls.Remove(messageKey);
DispatcherHelper.InvokeIfNecesary(() =>
{
//Raise event for the MainViewModel to stop displaying the long operation layer
StopLongOperationRequested?.Invoke(messageKey);
});
}
}
else
{
throw new Exception("Cannot End long operation that has not began");
}
}
}
}
Так что, как вы, вероятно, можете видеть, существует потенциальный тупик, если:
- Кто-то вызывает Begin из потока, не являющегося пользовательским интерфейсом.
- Входит в замок
- Кто-то вызывает Begin или End из потока пользовательского интерфейса и блокируется
- При первом вызове Begin выполняется попытка отправки в поток пользовательского интерфейса.
Результат: тупик!
Я хочу сделать этот поток-помощник безопасным, чтобы любой поток мог вызывать Begin или End в любой момент времени, заинтересованный в том, чтобы узнать, существует ли какой-либо известный шаблон, какие-либо идеи?
Спасибо!