What is the correct way to prevent reentrancy and ensure a lock is acquired for certain operations?

眉间皱痕 提交于 2019-12-05 03:25:17

There is one synchronization object in .NET that isn't re-entrant, you are looking for a Semaphore.

Before you commit to this, do get your ducks in a row and ask yourself how it can be possible that BeginProcess() can be called again on the same thread. That is very, very unusual, your code has to be re-entrant for that to happen. This can normally only happen on a thread that has a dispatcher loop, the UI thread of a GUI app is a common example. If this is truly possible and you actually use a Semaphore then you'll get to deal with the consequence as well, your code will deadlock. Since it recursed into BeginProcess and stalls on the semaphore. Thus never completing and never able to call EndProcess(). There's a good reason why Monitor and Mutex are re-entrant :)

mehrandvd

You can use Semaphore class which came with .NET Framework 2.0.

A good usage of Semaphores is to synchronize limited amount of resources. In your case it seems you have resources like Context which you want to share between consumers.

You can create a semaphore to manage the resources like:

var resourceManager = new Semaphore(0, 10);

And then wait for a resource to be available in the BeginProcess method using:

resourceManager.WaitOne();

And finally free the resource in the EndProcess method using:

resourceManager.Release();

Here's a good blog about using Semaphores in a situation like yours:

https://web.archive.org/web/20121207180440/http://www.dijksterhuis.org/using-semaphores-in-c/

There is very simple way to prevent re-entrancy (on one thread):

private bool bRefresh = false;
private void Refresh()
{
  if (bRefresh) return;
  bRefresh = true;
  try
  {
    // do something here
  }
  finally
  {
    bRefresh = false;
  }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!