System.ArgumentOutOfRangeException Имя параметра: chunkLength в System.Text.StringBuilder.ToString()

Я получил ниже исключения в файле журнала.

"System.ArgumentOutOfRangeException: индекс вышел за пределы диапазона. Должен быть неотрицательным и меньше размера коллекции. Имя параметра: chunkLength at System.Text.StringBuilder.ToString()"

Я считаю, что это из-за строки Builder, который не является потокобезопасным. Но я наткнулся на то, как сделать так, чтобы мой построитель строк был безопасным для потоков в ниже рекурсивной функции.

Любые идеи будут оценены. Благодарю.

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();
    }
}

1 ответ

Решение

Используя блокировку:

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
    }
}

Или переместите ваше статическое поле в локальную переменную внутри метода.

Другие вопросы по тегам