Когда параметр, переданный по ссылке, обновляется? - PullRequest
4 голосов
/ 01 июля 2010

Предположим, у меня есть такой метод:

public void MyCoolMethod(ref bool scannerEnabled)
{
    try
    {
        CallDangerousMethod();


    } 
    catch (FormatException exp)
    {
        try
        {
            //Disable scanner before validation.
            scannerEnabled = false;

            if (exp.Message == "FormatException")
            {
                MessageBox.Show(exp.Message);
            }
        }
        finally
        {
            //Enable scanner after validation.
            scannerEnabled = true;
        }
    }

И это используется так:

    MyCoolMethod(ref MyScannerEnabledVar);

Сканер может срабатывать в любое время в отдельном потоке. Идея состоит в том, чтобы не допустить этого, если мы обрабатываем исключение.

У меня вопрос: обновляет ли MyCoolMethod вызов MyScannerEnabledVar, когда установлен параметр scannerEnabled, или обновляет его при выходе из метода?

Примечание: я не писал этот код, я просто пытаюсь безопасно его реорганизовать.

Ответы [ 4 ]

5 голосов
/ 01 июля 2010

Вы можете рассматривать ссылку как , создающую псевдоним для переменной .Дело не в том, что передаваемая вами переменная «передается по ссылке», а в том, что параметр и аргумент являются одной и той же переменной , только с двумя разными именами.Таким образом, обновление одного немедленно обновляет другое, потому что в действительности здесь нет двух вещей:

Как отмечает SLaks, в VB существуют ситуации, в которых используется семантика копирование-в-копирование.Также, если я правильно помню, бывают редкие и неясные ситуации, в которых деревья выражений могут быть скомпилированы в код, который выполняет копирование-в-копирование, но я не вспоминаю подробности.

Если этот код предназначен для обновления переменной для чтения в другом потоке, тот факт, что переменная «немедленно» обновляется, вводит в заблуждение.Помните, что в можно наблюдать, как множественные потоки, чтения и записи перемещаются вперед и назад во времени относительно друг друга, если чтения и записи не являются энергозависимыми .Если намерение состоит в том, чтобы использовать переменную в качестве механизма связи между потоками, они используют объект, фактически предназначенный для этой цели, который безопасен для этой цели.Используйте какой-нибудь дескриптор ожидания или мьютекс или что-то еще.

4 голосов
/ 01 июля 2010

Обновляется в реальном времени, как это назначено внутри метода.

Когда вы передаете параметр по ссылке, среда выполнения передает (эквивалентно) указатель на поле или переменную, на которую вы ссылались. Когда метод присваивается параметру, он напрямую присваивается тому, на что указывает ссылка.

Заметьте, кстати, что это не всегда верно в VB.

1 голос
/ 01 июля 2010

Ситуация требует более простого рефакторинга.Отправленный вами код будет зависеть от условий гонки.Простое решение - заблокировать небезопасный метод, заставляя потоки переходить в очередь.Так оно и есть, в этом коде обязательно должны быть какие-то ошибки в приложении, но невозможно сказать, что именно они есть, не зная больше о ваших требованиях и реализации.Я рекомендую вам действовать осторожно, мьютекс / блокировка - это легко исправить, но может сильно повлиять на производительность.Если это вас беспокоит, то вам всем следует рассмотреть лучшее решение для обеспечения безопасности потоков.

1 голос
/ 01 июля 2010

Да, он будет установлен, когда переменная установлена ​​в методе. Возможно, было бы лучше вернуть true или false, если сканер включен, а не передавать его как ref arg

...