I believe the crux of the .NET MRE is thread affinity and its ability to let all waiting threads go through when Set is called. I found the use of the Semaphore works well. However, if I get 10 or 15 threads waiting, then I run into another issue. Specifically, it occurs when Set is called. In .Net, all waiting threads are released. Using a semphore does not release all. So I wrapped it in a class. NOTE: I am very familiar with .NET threading. I am relatively new to Java threading and synchronization. Nevertheless, I am willing to jump in and get some real feedback. Here's my implementation with assumptions that a Java novice would make:
public class ManualEvent {
private final static int MAX_WAIT = 1000;
private final static String TAG = "ManualEvent"; 
private Semaphore semaphore = new Semaphore(MAX_WAIT, false);
private volatile boolean signaled = false;
public ManualEvent(boolean signaled) {
    this.signaled = signaled; 
    if (!signaled) {
        semaphore.drainPermits();
    }
}
public boolean WaitOne() {
    return WaitOne(Long.MAX_VALUE);
}
private volatile int count = 0;
public boolean WaitOne(long millis) {
    boolean bRc = true;
    if (signaled)
        return true;
    try {
        ++count;
        if (count > MAX_WAIT) {
            Log.w(TAG, "More requests than waits: " + String.valueOf(count));
        }
        Log.d(TAG, "ManualEvent WaitOne Entered");
        bRc = semaphore.tryAcquire(millis, TimeUnit.MILLISECONDS);
        Log.d(TAG, "ManualEvent WaitOne=" + String.valueOf(bRc));
    }
    catch (InterruptedException e) {
        bRc = false;
    }
    finally {
        --count;
    }
    Log.d(TAG, "ManualEvent WaitOne Exit");
    return bRc;
}
public void Set() {
    Log.d(TAG, "ManualEvent Set");
    signaled = true;
    semaphore.release(MAX_WAIT);
}
public void Reset() {
    signaled = false;
    //stop any new requests
    int count = semaphore.drainPermits();
    Log.d(TAG, "ManualEvent Reset: Permits drained=" + String.valueOf(count));
}
}
Also note that I am basically betting that there's no more than a 1000 requests waiting for a release at any given time. By releasing and aquiring in batches, I am attempting to release any waiting threads. Note the call to WaitOne is working 1 permit at a time.