Блокировка C # и предупреждение анализа кода CA2002

StackOverflow https://stackoverflow.com/questions/1613588

  •  06-07-2019
  •  | 
  •  

Вопрос

В моем приложении есть форма, которая запускает процесс синхронизации, и по ряду причин я хочу разрешить запускать только одну синхронизацию одновременно. Поэтому я добавил в форму статическое поле bool, указывающее, выполняется ли синхронизация, и добавил блокировку, чтобы установить для этого поля значение true, если оно еще не установлено, чтобы первый поток мог начать синхронизацию, но когда он запускает все остальные потоки, постараюсь запустить его прекратит.

Мой код выглядит примерно так:

internal partial class SynchronizationForm : Form
{
    private static volatile bool workInProgress;

    private void SynchronizationForm_Shown(object sender, EventArgs e)
    {
        lock (typeof(SynchronizationForm))
        {
            if (!workInProgress)
            {
                workInProgress = true;
            }
            else
            {
                this.Close();
            }
        }
    }
}

Это работает хорошо, но когда я запускаю Code Analysis для моего проекта, я получаю следующее предупреждение:

  

CA2002: Microsoft.Reliability: SynchronizationForm.SynchronizationForm_Shown (object, EventArgs) блокирует ссылку типа «Тип». Замените это на блокировку объекта с сильной идентичностью.

Может кто-нибудь объяснить мне, что не так с моим кодом и как я могу улучшить его, чтобы предупреждение исчезло. Что это значит, что объект имеет сильную идентичность?

Это было полезно?

Решение

Что плохого в том, что вы блокируете что-то общедоступное ( typeof (SynchronizationForm) ), которое доступно везде из вашего кода, и если какой-то другой поток блокирует эту же вещь, вы получаете тупик. В общем случае рекомендуется блокировать только частные статические объекты:

private static object _syncRoot = new object();
...
lock (_syncRoot) 
{

}

Это гарантирует, что только SynchronizationForm может обладать блокировкой.

Другие советы

Проблема в том, что typeof (SynchronizationForm) не является частным объектом блокировки, что означает, что любой другой фрагмент кода может использовать его для блокировки, что может привести к взаимоблокировке. Например, если какой-то другой код сделал это:

var form = new SynchronizationForm();
lock(typeof(SynchronizationForm))
{
    form.SomeMethodThatCausesSynchronizationForm_ShownToBeCalled();
}

Тогда возникнет тупик. Вместо этого следует исключить частный объект блокировки в классе SynchronizationForm и заблокировать его вместо этого.

  

Объект System.Type класса удобно использовать в качестве блокировки взаимного исключения для статических методов класса.

Источник: http://msdn.microsoft. ком / EN-US / библиотека / aa664735 (VS.71) .aspx

Чтобы добавить к ответу Дага, у вас есть механизм блокировки, который должен использоваться только в статических методах, используемых в методе экземпляра.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top