РЕДАКТИРОВАТЬ: Это не то же самое, что сообщение "CRITICAL_SECTION in c #", как это было предложено кем-то еще.Этот пост о том, как определить код, который необходимо выполнить в критическом разделе.Предлагаемый повторяющийся пост спрашивает о том, как использовать Windows OS API для критических разделов.Даже близко не то же самое.
Изучение многопоточности и асинхронного кода.Немного борется с выявлением критических разделов.Не совсем уверен, что является общим и что является исключительным между переключениями контекста.Разница между тем, как обрабатываются типы значений и ссылочные типы.Обрабатывается ли в методе локальная переменная, внешняя переменная и передаваемый параметр.
Ниже приведен код, специально предназначенный для этого упражнения.Предположим, есть несколько потоков, которые могут вызывать метод с различными значениями параметров.Я также добавил пару переменных, внешних по отношению к методу.
Сначала давайте посмотрим, верны ли некоторые предположения.CS для удобства является «критической секцией».
++localX
должен находиться в CS, поскольку это локальная переменная.int localX = 0
нормально, потому что это атомарно в C #.т. е. поток не будет устанавливать localX
обратно в 0
для другого потока, когда он первоначально объявляет переменную. ++externalX
должен находиться в CS, поскольку он является общим ресурсом.И он должен быть объявлен как volatile, иначе поток может воздействовать на кэшированное значение и в результате получится неверный результат. externalParms.Add( parms[0] );
должен быть в CS, поскольку метод Add
не является потокобезопасным, и онэто общий ресурс.Также должен быть объявлен как volatile. myList[localX] = externalX;
должен находиться в CS, так как индексатор не является потокобезопасным и является локальной переменной.
Вопросы
- А как насчет кода ADO.NET?
using (var command = new SqlCommand(spName, connection))
Нужно ли беспокоиться о потоке, помещающем свой spName
в другой поток command
объект? command.Parameters.AddRange(parms);
Я добавляю значения в коллекцию.Это не потокобезопасно и должно быть в CS? await command.ExecuteNonQueryAsync();
command
является локальной переменной.Документация ничего не говорит о том, что метод ExecuteNonQueryAsync()
является потокобезопасным.CS или нет CS?
parms[0].Value = rnum;
должен быть в CS?
Произвольный код:
int externalX = 10;
List<SqlParameter> externalParms = new List<SqlParameter>();
internal async Task SampleExecuteNonQueryAsync(string spName, SqlParameter[] parms)
{
int localX = 0;
List<int> myList = new List<int>() { -1,-1};
Random rnd = new Random();
using (var connection = new SqlConnection(_connString))
{
await connection.OpenAsync();
using (var command = new SqlCommand(spName, connection))
{
++localX;
int rnum = rnd.Next(1, 100);
parms[0].Value = rnum;
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddRange(parms);
await command.ExecuteNonQueryAsync();
++externalX;
}
}
myList[localX] = externalX;
externalParms.Add( parms[0] );
}