1

我今天遇到了一段这样的 C# 代码:

lock(obj)
{
  //  perform various operations
  ...

  //  send a message via a queue but in the same process, Post(yourData, callback)
  messagingBus.Post(data, () => 
  {
    //  perform operation
    ...
    if(condition == true)
    {
      //  perform a long running, out of process operation
      operation.Perform();
    }
  }
}

我的问题是:回调函数是否可以在调用 operation.Perform() 之前以导致 lock(obj)被释放的方式调用?即,有没有一种方法可以在持有锁的同一线程上调用回调函数,并且在该线程释放锁之前?

编辑:messagingBus.Post(...) 可以被假定为插入到队列中,然后立即返回。回调在其他线程上调用,可能来自线程池。

对于 operation.Perform(),您可以将其读取为 Thread.Sleep(10000) - 只是运行很长时间并且不共享或改变任何状态的东西。

4

4 回答 4

0

I'm going to guess.

Post in .net generally implies that the work will be done by another thread or at another time.

So yes, it's not only possible that the lock on obj will be released before Perform is called, it's fairly likely it will happen. However, it's not guaranteed. Perform may complete before the lock is released.

That doesn't mean it's a problem. The "perform various actions" part may need the lock. messagingBus may need the lock to queue the action. The work inside may not need the lock at all, in which case the code is thread safe.

This is all a guess because there's no notion of what work is being done, why it must be inside a lock, and what Post or perform does. So the code may be perfectly safe, or it may be horribly flawed.

于 2012-07-19T20:12:39.617 回答
0

如果不知道messagingBus.Post 是如何实现的,就不可能回答您的问题。异步 API 通常不保证回调将真正并发执行。例如,.Net APM 方法(如 FileStream.BeginRead)可能决定同步执行操作,在这种情况下,回调将在调用 BeginRead 的同一线程上执行。在这种情况下,返回的 IAsyncResult.CompletedSynchronously 将设置为 true。

于 2012-08-11T15:14:51.893 回答
0

不知道messagingBus.Post 正在做什么,您无法分辨。 如果Post 调用给定的委托(您的示例中的 lambda 表达式),则该锁将在该 lambda 执行时到位。 如果Post 安排该委托在以后执行,则在 lambda 执行时锁将不会到位。目前尚不清楚 lock(obj) 的用途,锁定对 messingsBus.Post 的调用,或者什么...详细说明 messingBus 变量的类型(包括完整的命名空间)将大大有助于提供更好的细节。

于 2012-07-19T20:38:59.617 回答
0

如果回调异步执行,那么是的,当 Perform() 时,锁可能仍然被持有,除非 Post() 做一些特定的事情来避免这种情况(这将是不寻常的)。

如果回调被安排在与 Post() 调用相同的线程上(例如,在线程池只有 1 个线程的极端示例中),典型的线程池实现在线程完成当前任务之前不会执行回调,在这种情况下,这需要它在执行 Perform() 之前释放锁。

于 2012-08-11T14:54:14.973 回答