0

My WinForms application connects to a running service via WCF and subscribes to events from the service. When the event fires, my application requests current data from the service and calls a method named UpdateDisplay() to populate a DataGridView and display it. The grid view is remaining empty, and I'm trying to debug it. But if I put a breakpoint inside UpdateDisplay(), the next time the event fires, I get a deadlock because the first event handler hasn't finished yet.

I thought I could unsubscribe from the event at the top of my method and resubscribe to it at the bottom, something like this:

private static bool m_updatingDisplay = false;
private void UpdateDisplay()
{
    // Unsubscribe from the event while the display is being updated.  This should remove the problem of deadlocks while debugging because
    // the event gets raised again.
    m_callbackHandler.DatabaseUpdatedEvent -= m_callbackHandler_DatabaseUpdatedEvent;
    DoSomethingThatTakesALongTime(); 
    m_callbackHandler.DatabaseUpdatedEvent += m_callbackHandler_DatabaseUpdatedEvent;
}

But I still get the exception.

My only thought is to have the event handler merely set a flag, and then a timer would check the flag every minute or so, and if it's true, then it would do the update and clear the flag. I think that would work, but I have a feeling this is a common problem with a well-recognized solution, and I should probably know what it is. What's the best way to handle this situation?

ROBERT RICHARDSON
  • 2,077
  • 4
  • 24
  • 57
  • What execption do your get? How could this cause a deadlock? What is that handler doing? – Christopher Oct 31 '19 at 20:04
  • Now it's not happening. Sigh. I hate when my programs work when they're not supposed to. – ROBERT RICHARDSON Oct 31 '19 at 20:17
  • OK, now I got it. It happened when I exited from the first message handler. It's an InvalidOperationException, and the exception pop-up says, "This operation would deadlock because the reply cannot be received until the current Message completes processing. If you want to allow out-of-order message processing, specify ConcurrencyMode of Reentrant or Multiple on CallbackBehaviorAttribute." I don't want to use those attribute values because I don't understand them. Instead, I just want to stop handling the update event. – ROBERT RICHARDSON Oct 31 '19 at 20:21
  • Do you want to miss events that occur while you are running DoSomethingThatTakesALongTime() or do you want to wait to process that event until after the first update is finished? For instance: 1. receive DatabaseUpdatedEvent no 1 2. Start processing 3. Finish loading (still within ) 4. DatabaseUpdatedEvent no 2 is signalled but ignored (because we are still in DoSomethingThatTakesALongTime() 5. Finish updating the UI 6. Allow more events to be received 7. No more signals from DB for a long time. your UI now displays stale data (which is perhaps OK in your application) – Eric Linde Oct 31 '19 at 22:27
  • In this particular case, yes, I don't care about missing events. My function will finish and then the display will be updated. Specifically, I'm debugging. I have a breakpoint, and I'm trying to look closely at behavior at a specific point in time, with a specific set of data. I don't want a new event to fire that changes the set of data I am studying. In general, though, I don't know what the best way is of running a task from an event handler that may still be running when the next event fires. I suspect invoke() mentioned in the first answer is the best way. – ROBERT RICHARDSON Nov 01 '19 at 13:27

1 Answers1

0

The InvalidOpeartionException is a very odd Exception, because it covers a lot of possible things. All of those very specific to what function you call and what call it onto. The Documentation actually lists examples, but those really only showcase how little all the cases have in common:

  • Enumerators are supposed to become Invalid, if the underlying collection was changed. Hence they throw a IOE
  • For ResourceSet, it would be a case of the resource closed/disposed. Hence the IOE
  • XContainer.Add is specific to XML modification and the way that class does it's job. Hence the IOE
  • And the UI class case is soemthing we specifically invented to get people to properly use invoke.

So without you telling us exactly what DoSomethingThatTakesALongTime() and m_callbackHandler_DatabaseUpdatedEvent do - and wich specific line this exception is from - we can not hope to help you.

Christopher
  • 9,634
  • 2
  • 17
  • 31