我今天在我们的代码库中找到了以下方法,它让我觉得它可能不是线程安全的。我认为IEnumerable可能是一个引用类型,并且在执行此代码时可能会被另一个线程修改。这是正确的,还是这个方法毕竟是线程安全的?如果不是,这种方法是否适合静态?似乎使它成为一个实例方法不会改变在另一个线程中修改实体参数的可能性。
/// <summary>
/// Writes the Entity data in <paramref name="entities"/> to a CSV file located at <paramref name="path"/>.
/// </summary>
/// <typeparam name="T">The Entity Type.</typeparam>
/// <param name="entities">A List of Type LinqEntityBase.</param>
/// <param name="path">The location of the CSV file.</param>
internal static void LinqEntitiesToCsv<T>(IEnumerable<T> entities, string path) where T : LinqEntityBase
{
var entityBuilder = new StringBuilder();
List<KeyValuePair<string, int>> columnInfos = GetColumnInfos<T>();
for (int i = 0; i < columnInfos.Count; i++)
{
string columnName = columnInfos[i].Key;
entityBuilder.Append(columnName.Contains(',') ? columnName.WrapIn('\"') : columnName);
entityBuilder.Append(i < columnInfos.Count - 1 ? "," : string.Empty);
}
entityBuilder.Append(Environment.NewLine);
PropertyInfo[] propertyInfos = typeof (T).GetPropertiesFromCache().ToArray();
foreach (T entity in entities)
{
for (int i = 0; i < propertyInfos.Length; i++)
{
var columnAttribute = Attribute
.GetCustomAttribute(propertyInfos[i], typeof (ColumnAttribute))
as ColumnAttribute;
if (columnAttribute == null)
{
continue;
}
object value = propertyInfos[i].GetValue(entity, null);
string valueString = (value != null) ? value.ToString() : string.Empty;
entityBuilder.Append(valueString.Contains(',') ? valueString.WrapIn('\"') : valueString);
entityBuilder.Append(i < columnInfos.Count - 1 ? "," : string.Empty);
}
entityBuilder.Append(Environment.NewLine);
}
FileHelper.TryWriteTextFile(path, entityBuilder.ToString());
}
答案 0 :(得分:4)
你是对的。
该方法的实际安全性取决于你通过它的IEnumerable类型;螺纹安全很少存在于真空中。
例如,所有并发集合都完全线程安全,即使对于并发写入和枚举也是如此。
答案 1 :(得分:3)
事实上,当{1}}的底层数据结构被其他线程修改时,完全有可能在此方法迭代它时。
注意基础数据结构。 IEnumerable entities
本身不是一个具体的类,所以它可能是它背后的任何东西。
说完这个,方法是否是静态的没有区别,唯一的问题是所有线程是否共享IEnumerable
集合。