如何使静态变量线程安全?它在静态类中声明,并在静态扩展方法中递增

问题描述 投票:0回答:1

我有一些代码,如下所示。我正在尝试增加一个计数器并使其线程安全。 注意:我在这个方法中遗漏了不相关的代码。

public static class MyClass
{
    private static int m_Counter;
    public static int Counter
    {
        get { return m_Counter; }
    }

public static string MyMethod(this IWebDriver self, string testname = null)
{        
    Console.WriteLine("Test name: " + testname + ". Before incrementing Counter: " + Counter.ToString());
    Console.WriteLine("Test name: " + testname + ". Before incrementing m_Counter: " + m_Counter.ToString()); 
   
    Interlocked.Increment(ref m_DownloadsCounter);

    Console.WriteLine("Test name: " + testname + ". After incrementing Counter: " + Counter.ToString());
    Console.WriteLine("Test name: " + testname + ". After incrementing m_Counter: " + m_Counter.ToString());
}

我认为使用 Interlocked 会使变量线程安全,因为这里显示的答案 之前的 StackOverflow 答案

它不起作用。也许是因为我的技术堆栈和独特的情况。我正在跨测试装置(不在测试装置内)并行执行 Selenium Webdriver 和 Nunit 测试。

例如,以下 2 个测试调用 MyMethod。

如果我并行执行这些测试,控制台将打印以下内容

Test name: SampleTest_DownloadAndEditFiles. Before incrementing Counter: 0
Test name: SampleTest_DownloadAndEditFiles. Before incrementing m_Counter: 0
Test name: SampleTest_DownloadAndEditFiles. After incrementing Counter: 1
Test name: SampleTest_DownloadAndEditFiles. After incrementing m_Counter: 1
Test name: demoFileDownloads. Before incrementing Counter: 1
Test name: demoFileDownloads. Before incrementing m_Counter: 1
Test name: demoFileDownloads. After incrementing Counter: 2
Test name: demoFileDownloads. After incrementing m_Counter: 2

我反而期待以下内容

Test name: SampleTest_DownloadAndEditFiles. Before incrementing Counter: 0
Test name: SampleTest_DownloadAndEditFiles. Before incrementing m_Counter: 0
Test name: SampleTest_DownloadAndEditFiles. After incrementing Counter: 1
Test name: SampleTest_DownloadAndEditFiles. After incrementing m_Counter: 1
Test name: demoFileDownloads. Before incrementing Counter: 0
Test name: demoFileDownloads. Before incrementing m_Counter: 0
Test name: demoFileDownloads. After incrementing Counter: 1
Test name: demoFileDownloads. After incrementing m_Counter: 1

我需要在代码中添加或删除什么?或者我需要放弃一切并使用不同的方法吗?

我不确定是否需要完整的堆栈跟踪来回答这个问题,但下面是该跟踪。这就是测试方法到达MyMethod的方式。

首先是基类

public class TestBase
{
Browser = new ChromeDriver(cService, new BaseChromeOptions(), commandTimeout);
}

接下来是测试课

[LocalSeleniumTestFixture(BrowserNames.Chrome)]
[LocalSeleniumTestFixture(BrowserNames.Firefox)]
[TestFixture]
public class MyTests : TestBase
{
    public MyTests(string browserName) : base(browserName) { }
    [Test]
    public void demoFileDownloads()
    {       
     Browser.Navigate().GoToUrl("https://www.selenium.dev/selenium/web/downloads/download.html");
IWebElement btn1 = Browser.FindElement(By.Id("file-1"));         
        btn.ClickAndWaitForDownload(Browser, "demoFileDownloads");
    }
}

测试类调用 WebElementExtensions

public static class WebElementExtensions
{
    public static string ClickAndWaitForDownload(this IWebElement self, IWebDriver Browser, string testname = null)
    {
        self.Click();

        return Browser.MyMethod(testname);
    }
}
c# selenium-webdriver nunit
1个回答
0
投票

借助

Concurrent
系列,您可以实现您想要的目标。例如:

public static class MethodCounter
{
    private static ConcurrentDictionary<string, int> m_counters = new ConcurrentDictionary<string, int>();
    public static ConcurrentDictionary<string, int> Counters
    {
        get { return m_counters; }
    }

    public static void Increment(string methodName)
    {
        m_counters.AddOrUpdate(methodName, 1, (key, existingValue) => existingValue + 1);
    }

    public static int GetCount(string methodName)
    {
        if (m_counters.TryGetValue(methodName, out var count))
        {
            return count;
        }
        return 0;
    }
}

增加它:

MethodCounter.Increment(testname);

通过以下方式访问它:

MethodCounter.GetCount(testname);
© www.soinside.com 2019 - 2024. All rights reserved.