2010-05-05 96 views
3

使用锁定时,锁定的对象必须是对象。例如,这是合法的使用除锁定对象以外的其他锁定线程

static DateTime NextCleanup = DateTime.Now; 
    const TimeSpan CleanupInterval = new TimeSpan(1, 0, 0); 
    private static void DoCleanup() 
    { 
     lock ((object)NextCleanup) 
     { 
      if (NextCleanup < DateTime.Now) 
      { 
       NextCleanup = DateTime.Now.Add(CleanupInterval); 
       System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(cleanupThread)); 
      } 
     } 
     return; 
    } 

回答

6

请注意,即使您在此尝试做的事情是可能的(例如,如果DateTime是引用类型,因此您可以锁定),但这并不合法,因为您将NextCleanup设置为lock区块内的新值。

您无法在锁定该对象的代码块中设置对新对象的引用。

这就是为什么建议有一个专用的“锁”对象用于所有需要同步以用于相关目的的代码。

+1

这是第一个很好的解释,为什么你应该使用一个单独的对象进行锁定,而不是你计划使用的对象。 – 2010-05-05 18:33:08

10

您可以锁定任何引用类型。

由于DateTime不是引用类型,因此无法锁定它。
如果您尝试,每次拨打电话Monitor.Enter都会收到一个不同的盒装DateTime值,并且锁定将无效。

你想做什么?
就运行时而言,无论您锁定哪个对象都无关紧要。 (锁定一个对象不会奇迹般地阻止其他线程使用该对象,除非它们明确地锁定在同一个对象上)
当你锁定一个对象时,你应该选择一个对象,所有必要的代码段将锁定。请参阅CA2002

+2

应该注意的是,所有的引用类型都是对象,所以不需要投射。另外,确保你使用的变量锁总是指向同一个对象。 – 2010-05-05 18:23:24

+0

伟大的答案 - 我将不得不记住这一点,以备将来参考! – Dave 2010-05-05 18:26:19

+0

我想要做的只是防止另一个线程检查,看看它是否可以更新之前已经过去了一小时。 – 2010-05-05 18:29:34

0

它不System.Object类型的,但有一个理由不使用一个对象?

+0

阅读我的更新。我的意思是'System.Object'。 – 2010-05-05 18:23:28

+0

我想约翰在说什么,它不需要像输入的OP那样转换为System.Object。或者他可能意味着你不必创建一个System.Object成员,然后使用* that *作为锁。我只是这样说,因为作为一个新手,我以前只是为了锁定而创建了一个System.Object,因为所有东西都是从System.Object派生的,所以我几乎可以使用任何东西。 – Dave 2010-05-05 18:25:20

+0

@SLaks:它必须是一个参考类型。我认为约翰意味着它不一定是最小的'System.Object',但可以是从它派生的任何引用类型。 – 2010-05-05 18:25:33

1

看起来你正在试图做的是定期运行一个清理程序。如果是这种情况,可以使用System.Threading.Timer,它专门用于运行定期任务。