0

I'm trying to do something like this:

EventWaitHandle handler = new EventWaitHandle(false, EventResetMode.AutoReset)

//This code will run in background thread
private void AsyncWait() {
    while (true) {
        handler.WaitOne();
        //LongRunningOperation()
    }
}

Elsewhere in the code, there will be methods that call:

handler.Set()

So the LongRunningOperation() is executed..

Problem is, the handler.Set() can be called again while the AsyncWait() thread is running the LongRunningOperation()

This makes the LongRunningOperation() will never be called whenever the handler.Set() is called while AsyncWait() is still executing LongRunningOperation()

How to make this right? :(

David Pilkington
  • 13,528
  • 3
  • 41
  • 73
ch0eb1t
  • 103
  • 8
  • If you called `handler.Set()`, `handler.Set()`, `handler.WaitOne()`, `handler.WaitOne()` are you wanting the last `WaitOne()` to not block because `Set` was called twice before? – Scott Chamberlain Nov 06 '13 at 06:46
  • @Scott Chamberlain, exactly – ch0eb1t Nov 06 '13 at 07:20
  • You are using `EventResetMode.AutoReset` so even when `LongRunningOperation()` is running the `handler` was already (automatically) reset, so when you call `handler.Set()` during the `LongRunningOperation()`, it won't cause the next `handler.WaitOne();` to block as it was already reset directly after waiting for it. So either there is no problem or either I think I don't see your problem clearly... – Stormenet Nov 06 '13 at 07:54
  • @Stormenet No, the next handler.WaitOne() will block. – ch0eb1t Nov 06 '13 at 08:58
  • It shouldn't, see the following example (create standard windows forms project and replace Form1 code): http://pastebin.com/bCqYdpSm For me it outputs `Pass: 1 Pass: 2` – Stormenet Nov 06 '13 at 12:25

1 Answers1

1

Use a Semaphore instead of AutoResetEvent.

A semaphore uses a counter internally. You can also define the maximum number of threads that can be "let through" at a time.

readonly Semaphore _semaphore = new Semaphore(0, int.MaxValue);

public void Enqueue<T>(T item)
{
     _internalQueue.Enqueue(item);
     _semaphore.Release();  // Informs that deque task to unblock if waiting. Equivalent to the  WaitHandle.Set() method. Increases the semaphore counter
}

public T Dequeue()
{
     _semaphore.WaitOne();   // Blocks as long as there are no items in the queue. Decreases the semaphore counter when "let through". Blocks the thread as long as semaphore counter is zero.
     return _internalQueue.Dequeue();
}
Frode
  • 3,325
  • 1
  • 22
  • 32