我在日志文件中遇到以下异常。
" System.ArgumentOutOfRangeException:索引超出范围。必须是非负数且小于集合的大小。 参数名称:chunkLength 在System.Text.StringBuilder.ToString()"
我认为这是因为字符串生成器不是线程安全的。但我偶然发现如何使我的字符串生成器在下面的递归函数中保持线程安全。
任何想法将不胜感激。感谢。
public static class StringExtensions
{
/// <summary>
/// The log key builder
/// </summary>
private static StringBuilder logKeyBuilder;
public static string ConcatLogKeyWithExceptionMessage<T>(this T entity, string configuredLogKeys, bool logOnlySingleKey, string exceptionMessage, bool firstInvocation = true) where T : class
{
logKeyBuilder = logKeyBuilder ?? new StringBuilder();
if (entity != null)
{
var objType = entity.GetType();
var properties = objType.GetProperties();
foreach (var property in properties)
{
var propValue = property.GetValue(entity, null);
var elems = propValue as IList;
if (elems != null)
{
foreach (var item in elems)
{
{
ConcatLogKeyWithExceptionMessage(item, configuredLogKeys, logOnlySingleKey, exceptionMessage, false);
}
}
}
else
{
// This will not cut-off System.Collections because of the first check
if (property.PropertyType.Assembly == objType.Assembly)
{
ConcatLogKeyWithExceptionMessage(propValue, configuredLogKeys, logOnlySingleKey, exceptionMessage, false);
}
else
{
configuredKeysArray = configuredKeysArray ?? (!string.IsNullOrEmpty(configuredLogKeys) ? configuredLogKeys.Split(',') : new string[0]);
foreach (var configLogKey in configuredKeysArray)
{
if (string.Compare(configLogKey.Trim(), property.Name.Trim(), StringComparison.OrdinalIgnoreCase) == 0)
{
configuredKeysArray = configuredKeysArray.Where(x => x != configLogKey).ToArray();
logKeyBuilder.Append(property.Name);
logKeyBuilder.Append(" ");
logKeyBuilder.Append("-");
logKeyBuilder.Append(" ");
logKeyBuilder.Append(property.GetValue(entity));
logKeyBuilder.Append(" ");
if (logOnlySingleKey)
{
break;
}
}
}
}
}
}
}
logKeyBuilder = firstInvocation ? logKeyBuilder.Append(exceptionMessage) : logKeyBuilder;
return logKeyBuilder.ToString();
}
}
答案 0 :(得分:0)
使用锁定:
private static object lockObject = new object();
public static string ConcatLogKeyWithExceptionMessage<T>(this T entity, string configuredLogKeys, bool logOnlySingleKey, string exceptionMessage, bool firstInvocation = true) where T : class
{
lock(lockObject )
{
// rest of your code here
}
}
或者将静态字段移动为方法内的局部变量。