EDIT:This is not the same thing as the post "CRITICAL_SECTION in c#" as suggested by someone else. This post is about how to identify code that needs to be done in a critical section. The suggested duplicate post is asking about how to use the Windows OS API for critical sections. Not even close to the same.
Learning about multi-threading and async code. Struggling a bit with identifying critical sections. Not really sure what is shared and what is exclusive between context switches. Difference between how value types and reference types are handled. Whether a local variable vs. external variable vs. a parameter passed in is handled in a method.
Below is some code just specifically for this exercise. Assume there are multiple threads that can call into the method with different parameter values. I also added a couple variables external to the method too.
First lets see if some assumptions are correct. CS is "critical section" for convenience.
++localX
needs to be in a CS since it is a local variable. int localX = 0
is ok because this is atomic in C#. i.e. a thread won't set localX
back to 0
for another thread when it initially declares the variable.++externalX
needs to be in a CS since it is a shared resource. And needs to be declared volatile or a thread might act on a cached value and end up with the wrong result.externalParms.Add( parms[0] );
needs to be in a CS since the Add
method is not thread safe and it is a shared resource. Should also be declared volatile.myList[localX] = externalX;
needs to be in a CS since the indexer is not thread safe and it is a local variable.Questions
using (var command = new SqlCommand(spName, connection))
Do I need to worry about a thread putting its spName
into another threads command
object?command.Parameters.AddRange(parms);
I'm adding values to a collection. This is not threadsafe and needs to be in a CS?await command.ExecuteNonQueryAsync();
command
is a local variable. Documentation doesn't say anything about the ExecuteNonQueryAsync()
method being threadsafe. CS or no CS?parms[0].Value = rnum;
needs to be in a CS?Arbitrary code:
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] );
}
答案 0 :(得分:0)
我认为您感到困惑和思考过多。
任何基于“堆栈”的变量(即局部变量)都是“每个线程”的,因此无需为其锁定任何内容,每个线程将具有一个完全独立的线程。
如果您担心多个线程将访问r":-?[()]|([^A-Za-z0-9(),!?'`])"
,请使用为此目的而创建的集合之一:https://docs.microsoft.com/en-us/dotnet/standard/collections/thread-safe/