Question

I am writing a single-threaded script to make a bunch of programmatic changes to a database. Certain actions cause the database to perform some internal actions that take a while to fully resolve.

At the moment, my code includes a method that looks like this:

public static void AwaitTemplatePropagation(this Connection conn, DBObject template)
{
    while ((int)template["TransactionCount"] > 0)
    {
        System.Threading.Thread.Sleep(100);
    }
}

Basically, it polls every 100 milliseconds until the outstanding transaction count reaches 0.

However, it is also possible to subscribe to an event called PropertyUpdated on the DBObject class, which will be raised when the TransactionCount property changes. I would prefer to use this and have the server let me know when to continue, rather than polling. I imagine it should look something like this:

public static void AwaitTemplatePropagation(this Connection conn, DBObject template)
{
    template.PropertyUpdated += ???; // Something?

    template.RegisterForPropertyUpdates(new string[] { "TransactionCount" });

    // Magic happens?

    template.UnregisterPropertyUpdates(new string[] { "TransactionCount" });
    template.PropertyUpdated -= ???; // Unsubscribe the event handler
    // Return to the calling function in the main thread
}

What I am having trouble figuring out is, how do I write a function which simply sets up the subscription, then blocks until a PropertyChangedEvent fires which says "the TransactionCount is now zero"? At that point I want to remove the subscription and return execution to where I was in the middle of the main script.

I'm using .NET 4.0, so async/await keywords aren't available. I'm not sure they would help anyway.

Was it helpful?

Solution

You can use a ManualResetEventSlim

private static ManualResetEventSlim _event = new ManualResetEventSlim (false);

public static void AwaitTemplatePropagation(this Connection conn, DBObject template)
{
    template.PropertyUpdated += OnPropertyUpdated; // Something?

    template.RegisterForPropertyUpdates(new string[] { "TransactionCount" });

    // Magic happens?
    // if you are using this method many times you have to reset the event first
    _event.Reset(); //Sets the state of the event to nonsignaled, which causes threads to block.
    _event.WaitHandle.WaitOne();

    template.UnregisterPropertyUpdates(new string[] { "TransactionCount" });

    // Return to the calling function in the main thread
 }

public void OnPropertyUpdated(...)
{
    _event.Set();
}

ManualResetEventSlim performance

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top