【问题标题】:Different thread share an object不同的线程共享一个对象
【发布时间】:2011-05-21 19:47:43
【问题描述】:

我有以下代码片段,可以被不同的线程访问。

         try
         {            
            this.RefreshSettings();
            DateTime lastChecked = DateTime.Now.AddMilliseconds(-1 * m_Settings.Interval);

            while (Run)
            {
                if ((DateTime.Now - lastChecked).TotalMilliseconds >= this.m_Settings.Interval)
                {
                    lastChecked = DateTime.Now;

                    if (this.ShouldNotify())
                    {
                        object LockObj = new object();

                        lock (LockObj)
                        {
                            this.Notify();
                        }
                    }
                }
                //Thread.Sleep(this.m_Settings.Interval);
            }
         }

如您所见,我只希望在每个给定的时间间隔 (m_settings.Interval) 之后调用 ShouldNotify() 方法。但是,我的问题是,如果两个或多个线程调用了 NotifyIfNecesarry 函数,它们共享 lastChecked 变量。因此,如果一个线程将其值重置为 dateTime.Now,它也会为其他线程重置。

如何编写该方法以使每个线程都维护自己的 lastChecked?使用 Thread.Sleep 不是一个选项,因为当 bool Run 的值更改为 false 时,我需要循环立即退出。如果我有一个thread.Sleep,并且线程正在休眠,程序在检查while条件之前不会退出,因此m_settings.Interval可能存在mak延迟。

【问题讨论】:

  • 除非我遗漏了什么,否则lastChecked 变量是本地的,但您说它正在与此方法的其他实例共享。局部变量不在线程之间共享,所以是我遗漏了什么还是您遗漏了什么?
  • 这段代码在哪里?它是在线程的运行中还是在另一个类中?
  • @Coding Gorilla:lastChecked 是本地的。我不知道线程不共享局部变量。我想那一定是其他原因导致了这个问题。
  • @Coding Gorilla 的假设是每个线程都有一个单独的对象。如果您正在共享对象,那么您仍然有问题(可能与您的设计有关)。

标签: c# multithreading


【解决方案1】:

您应该跳过循环并使用例如System.Timers.Timer。而且你的锁也不合适。它应该在循环之外创建,而不是每个实例。使用锁时,所有线程必须锁定同一个对象。

【讨论】:

  • @Mickael 我认为您的意思是“跳过你的循环”而不是“跳过你的厕所”。虽然这句话可能让我微笑因为en.wikipedia.org/wiki/Skip_to_My_Lou
  • 我注意到了,并编辑了答案 :) 也给了我一个微笑。
【解决方案2】:

你为什么不简单地使用一个计时器对象?

要么:System.Windows.Forms.Timer 或:System.Threading.Timer

【讨论】:

    【解决方案3】:

    在本地创建的对象上lock 没有任何意义。所有线程必须lock 在同一个实例上,否则将不会同步。

    下面的代码无法按预期工作,因为运行此代码的所有线程都将拥有对新创建的object 实例的本地引用。

    object LockObj = new object();
    
    lock (LockObj)
    {
       this.Notify();
    }
    

    另外,由于lastChecked 是本地值类型,每个线程拥有自己的副本。

    【讨论】:

      【解决方案4】:

      我怎样才能写出这样的方法 每个线程都维护自己的 上次检查

      你已经这样做了。

      编码大猩猩是对的。

      lastChecked 变量是 local...局部变量不共享 线程之间

      【讨论】:

        猜你喜欢
        • 2016-05-03
        • 2012-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多