Ошибка ссылки на объект при создании не статического класса в нескольких потоках - PullRequest
0 голосов
/ 27 апреля 2019

Я использую C # и NUnit Framework для одновременного выполнения нескольких тестов в разных потоках. Я хочу записать время между определенными действиями и создал класс ActionTimeHelper для того же самого.

Ниже приведен код класса и контекст, в котором используются методы в классе

Когда я запускаю два параллельных теста, один из которых вызывает метод Login, тогда завершается только один тест, а другой выдает ошибку

(Message: System.NullReferenceException : Object reference not set to an instance of an object.
) at actionList.Add(new ActionTimeInfo()

Я сделал actionList как ThreadStatic, чтобы каждый тест, выполняющийся в своем собственном потоке, имел свою собственную копию, поэтому я не могу понять, почему возникает ошибка.

Примечание: если я запускаю один тест за раз, все работает нормально

Может кто-нибудь, пожалуйста, направьте меня в этом. Спасибо за помощь.

Прочитал некоторые статьи Ссылка на не статический член с экземпляром объекта , Ссылка на экземпляр объекта в статическом классе (c #) , но не в состоянии связать мою конкретную проблему

public static class ActionTimeHelper
{
private static readonly string _actionTimeLogFileName = "ActionTimeLog_" + string.Format("{0:yyyy_MM_dd_hhmmss}", DateTime.Now);
[ThreadStatic] private static FileStream _fileStream = null;
[ThreadStatic] private static StreamWriter _actionStreamWriter = null;
[ThreadStatic] private static JsonWriter _jsonWriter = null;
[ThreadStatic] private static List<ActionTimeInfo> actionList = new List<ActionTimeInfo>();

public static void CreateActionTimeLogFile(string logPath, string testName)
{
    string dir = logPath + testName + @"\";
    if (!Directory.Exists(dir))
    {
        Directory.CreateDirectory(dir);
    }
    _fileStream = File.Open(dir + _actionTimeLogFileName + ".json", FileMode.CreateNew);
    _actionStreamWriter = new StreamWriter(_fileStream);
    _jsonWriter = new JsonTextWriter(_actionStreamWriter);
    _jsonWriter.Formatting = Formatting.Indented;
    JsonSerializer serializer = new JsonSerializer();
    serializer.Serialize(_jsonWriter, actionList);
    _fileStream.Flush();
    _actionStreamWriter.Flush();
    _jsonWriter.Flush();

}

public static void StartActionTime(string actionName)
{

    actionList.Add(new ActionTimeInfo()
    {
        TestName = TestContext.CurrentContext.Test.Name,
        ActionName = actionName,
        StartTime = DateTime.Now
    });
}

public static void EndActionTime(string actionName)
{
    ActionTimeInfo endAction = actionList.Find(actionInfo => actionInfo.ActionName.Equals(actionName));
    endAction.EndTime = DateTime.Now;
    endAction.ExecutionTime = endAction.EndTime.Subtract(endAction.StartTime);
}

}

public class ActionTimeInfo
{
public string TestName { get; set; }

public string ActionName { get; set; }

public DateTime StartTime { get; set; }

public DateTime EndTime { get; set; }

public TimeSpan ExecutionTime { get; set; }
}


public void Login(string username, string password)
{
    ActionTimeHelper.StartActionTime("Navigating to URL");
    ActionTimeHelper.EndActionTime("Navigating to URL");
    ActionTimeHelper.StartActionTime("Login Action");
    ActionTimeHelper.EndActionTime("Login Action");
    Thread.Sleep(30000);
}

[TearDown]
public void TestTearDown()
{
    ActionTimeHelper.CreateActionTimeLogFile(LogPath, TestContext.CurrentContext.Test.Name);
}

Фактический результат: ошибка нулевого задания Ожидаемый результат: нет нулевой ссылки на ошибку

1 Ответ

1 голос
/ 27 апреля 2019

«Не указывайте начальные значения для полей, помеченных ThreadStaticAttribute, потому что такая инициализация происходит только один раз, когда выполняется конструктор класса, и, следовательно, влияет только на один поток. Если вы не укажете начальное значение, вы можете полагаться на то, что поле инициализируется значением по умолчанию, если оно является типом значения, или нулевым, если оно является ссылочным типом. «

С

https://docs.microsoft.com/en-us/dotnet/api/system.threadstaticattribute?view=netframework-4.8

...