bmt22033
bmt22033

Reputation: 7240

Block code and wait for event handler to fire?

I'm writing an application that uses a 3rd party library to process some data. In a very simplified example, I have a method which runs as a task like this:

private void ProcessListOfItems(List<string> items)
{ 
    while (items.Count > 0)
    {
        3rdPartyLibObject.Process(items[0]);
        items.Remove(0);
    }
}

As you can see, the way my code is currently written, I remove each item from the list as soon as the Process() method returns. But it's possible that the processing of an item could fail and I need to know if that happens. Unfortunately, the Process() method does not return a bool value to indicate that the item was successfully processed or not but rather it will fire ProcessingComplete and ProcessingFailed events. I have event handlers hooked up to those events like this:

3rdPartyLibObject.ProcessingComplete += obj_ProcessingSuccess;
3rdPartyLibObject.ProcessingFailed += obj_ProcessingFailed;

private void obj_ProcessingSuccess(object sender, 3rdPartyLibObject.ProcessingEventArgs e)
{
    this.Invoke(new ProcessedHandler(OnProcessed), new object[] { true });
}

private void obj_ProcessingFailed(object sender, 3rdPartyLibObject.ProcessingEventArgs e)
{
    this.Invoke(new ProcessedHandler(OnProcessed), new object[] { false });
}

private void OnProcessed(bool success)
{
    if (success)
    {
        Debug.WriteLine("Item was processed succesfully!");
    }
    else
    {
        Debug.WriteLine("Failed to process item!");
    }
}

What I'd like to do is have my code block right after the call to 3rdPartyLibObject.Process() and until one of the event handlers fires so I know if the item failed to process or not (and whether I should remove it from the list or not). I'm guessing that this is probably not an uncommon situation but I've never run into it before. Is there a generally agreed upon best practice for dealing with this kind of scenario?

Upvotes: 3

Views: 6132

Answers (2)

Matt Burland
Matt Burland

Reputation: 45135

Would this work:

private bool itemProcessed = false;

private void ProcessListOfItems(List<string> items)
{ 
    while (items.Count > 0)
    {
        3rdPartyLibObject.Process(items[0]);
        if (itemProcessed)
        {
            items.Remove(0);
        }
    }
}

private void obj_ProcessingSuccess(object sender,    3rdPartyLibObject.ProcessingEventArgs e)
{
    this.itemProcessed = true;
}

private void obj_ProcessingFailed(object sender, 3rdPartyLibObject.ProcessingEventArgs e)
{
    this.itemProcessed = false;
}

Assuming the event all fire on the same thread, the handlers should be called before you process the next item.

Upvotes: 1

Reed Copsey
Reed Copsey

Reputation: 564413

Personally, I would wrap this into a Task<bool>, like so:

Task<bool> Process3rdParty(ThirdPartyLibObject thirdParty, string item)
{
    var tcs = new TaskCompletionSource<bool>();

    thirdParty.ProcessingComplete += (o, e) => tcs.SetResult(true);
    thirdParty.ProcessingFailed += (o, e) => tcs.SetResult(false);

    thirdParty.Process(item);

    return tcs.Task;
}

You could then call this like so:

private void ProcessListOfItems(List<string> items)
{ 
    while (items.Count > 0)
    {
        var task = Process3rdParty(thirdPartyLibObject.Process(items[0]);
        if (task.Result)
            items.Remove(0);
    }
}

This would also simplify things if you decided, later, that you wanted this to run asynchronously or to process multiple items at once (if the third party library supports this). This would also be very simple to move to C# 5's async/await support to make the entire thing asynchronous.

Upvotes: 12

Related Questions