English 中文(简体)
C# Multithreading - Telling a waiting process that the first process has finished using the locked code?
原标题:

I understand that when developing multithreaded applications you must synchronize access to shared memory using either, for instance, a monitor or a lock.

QUESTION

How do you tell the waiting process(proc2) that the process using the locked code block (proc1) has finished using the code?

最佳回答

Are you talking about real operating system processes, or just tasks within a process?

If it s just tasks within a process, you typically just let locks do the work for you. The second task tries acquire the lock that the first task currently owns, and just blocks. When the first task releases the lock, the second task is automatically unblocked.

If you want to the second thread to have the option of doing other work first, you could use Monitor.TryEnter instead - although that s slightly more fiddly.

If you want to wait but you have more sophisticated requirements than just locking, then Monitor.Pulse/PulseAll/Wait are probably called for. See the second half of this page for an example.

If you re actually talking about processes then you ll need to use a system-wide structure such as a Mutex. These are "heavier" than in-process .NET monitors, but allow for inter-process coordination.

问题回答

The other process is usually blocked, waiting to grab the lock. When your first process releases it, the second process can grab it.

In other words, in a typical scenario, you don t tell the other thread to go, instead you stop preventing it from going.

(There are scenarios where you do want to tell a thread to go, usually handled by a AutoResetEvent or a ManualResetEvent)

To do this, you ll need to make use of the various synchronization objects available in C#. Some examples of the available synchronization objects are System.Threading.Mutex, System.Threading.Semaphore, System.Threading.ManualResetEvent, and System.Threading.AutoResetEvent (this is not an exhaustive list, but it s the basics). The exact synchronization object you ll want depends on your specific needs.

Mutex is probably the simplest to use, so I ll give it as an example. Say I have two functions that are running in two different threads (I ll stick with your own examples, proc1 and proc2). Both functions need to access the same variable, foo. In each function that accesses foo, you ll need to "lock" your mutex first. Then do whatever you need to do, then unlock it.

For example:

class bar
{
  private int foo;
  private System.Threading.Mutex lock = new System.Threading.Mutex;

  public void proc1()
  {
    lock.WaitOne();

    // do stuff to foo

    lock.ReleaseMutex();
  }

  public void proc2()
  {
    lock.WaitOne();

    // do stuff to foo

    lock.ReleaseMutex();
  }
};

Using this method, proc1 will execute. It will try to "grab" the mutex (lock). If the mutex is already grabbed, proc1 will go to sleep until the mutex is "released" by the other thread - proc1 will sit and wait, doing nothing (and eating no CPU cycles!) until the mutex is released. Then it will lock it and do its thing. No other thread will be able to grab the mutex until proc1 is done with it.

Another option is to use an Event. C# provides two types of events - manual reset and autoreset. I ll use a manual reset event for my example.

class bar
{
  private System.Threading.ManualResetEvent event = new System.Threading.ManualResetEvent;

  public void proc1()
  {
    // do stuff

    event.Set();
  }

  public void proc2()
  {
    event.WaitOne();
    event.Reset();

    // do stuff
  }
};

In this example, when proc2 is running it goes to sleep when it hits "event.WaitOne" and uses no CPU cycles until proc1 "sets" the event. Setting the event causes proc2 to wake up, and now it can do its thing. Because this is a manual reset event, the event will stay in the "set" state until event.Reset() is called.

Depending on the nature of the multithreading, Thread.Join may do the trick. It blocks the calling thread until the thread terminates, while continuing to perform standard message pumping.





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签