Block code and wait for event handler to fire?

こ雲淡風輕ζ 提交于 2019-12-06 08:31:43

问题


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?


回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/12900574/block-code-and-wait-for-event-handler-to-fire

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!