【问题标题】:Shared variables between thread and UI C#线程和 UI C# 之间的共享变量
【发布时间】:2012-07-17 09:49:05
【问题描述】:

我可以在两个线程之间安全地共享这个“状态”对象吗?

    private bool status = false;

    private void uiNewThread_bootloaderStartIdSetupAuto()
    {
        while (status)
            ;
    }

上面是将从下面的 UI 启动的新线程:

    private void uiBtnBootloaderStartIdSetupAuto_Click(object sender, EventArgs e)
    {
        if (MessageBox.Show("ID will be setup starting from 1 to 16. \n\nAfter pressing 'YES', press the orange button one-by-one on the nodes.\nThe first pressed node will have number 1, the next number 2, and so on... \n\nWhen done, hit DONE button.", "ID setup", MessageBoxButtons.YesNo) == DialogResult.Yes)
        {
            status = true;
            Thread transmitConfig = new Thread(new ThreadStart(uiNewThread_bootloaderStartIdSetupAuto)); //close port in new thread to avoid 
            transmitConfig.Start();
        }
        else
        {
            Log(LogMsgType.Normal, "User cancelled");
            status = false;            
        }
    }

【问题讨论】:

    标签: c# windows multithreading


    【解决方案1】:

    编译器或 CPU 进行的缓存或重新排序等优化可能会破坏您的代码。您应该声明字段volatile 以防止这种情况:

    private volatile bool status = false;
    

    一个可能出错的例子是,如果两个线程在不同的内核上运行,status 的值可能会被运行轮询线程的内核缓存在 CPU 寄存器中,因此永远看不到该值由其他线程更新。

    尝试在发布模式下构建您的应用,您应该会看到这种效果。

    【讨论】:

    • 在大多数 cpu 架构和 .net 框架中,volatile 或多或少是多余的。乔达菲在这里讨论。 bluebytesoftware.com/blog/2010/12/04/SayonaraVolatile.aspx
    • @stevethethread:在我的系统上,我无数次地重新创建了这个场景,并在 .NET 中遇到了死锁。这里的问题很现实。
    • 可悲的是,即使正常情况下使用volatile 一切正常,volatile write 也不能保证写入将在宇宙热死之前完成:-)跨度>
    • @xanatos:实际上在这里您需要volatile 进行读取,因为即使没有关键字,.NET 中的写入也是易变的。
    • 使用 Volatile 关键字只是为了防止内存读/写的重新排序,并且大多数现代 cpu 架构已经强制执行此操作,.net 框架也是如此。将变量标记为 volatile 的关键在于,对该变量的所有读取和写入都是 volatile 的,这可能有点矫枉过正,因此性能不是很好。如果只在一个地方相关,一个简单的锁就足够了。
    【解决方案2】:

    你最好只锁定变量,例如

    private static readonly object _lock = new Object();
    
    ....
    
    lock(_lock){
    //access to boolean variable etc.
    }
    

    另一种可能性是将 bool 包装在 Lazy 中,并且对内部值的访问是线程安全的。

    如果您想使用无锁机制来读取和更新值,您可以考虑使用 Interlocked 类中的方法。

    这里的信息:

    System.Threading.Interlocked

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-22
      • 1970-01-01
      • 2012-10-27
      • 2013-07-26
      • 2019-01-28
      • 2021-01-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多