阻止代码并等待事件处理程序触发? [英] Block code and wait for event handler to fire?

查看:134
本文介绍了阻止代码并等待事件处理程序触发?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个使用第三方库处理一些数据的应用程序。在一个非常简单的例子中,我有一个方法作为一个这样的任务运行:

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

正如你所看到的,我的代码当前的方式写入后,一旦Process()方法返回,我就从列表中删除每个项目。但是可能的是处理一个项目可能会失败,我需要知道是否发生这种情况。不幸的是,Process()方法不返回一个bool值来指示该项目是否被成功处理,而是会触发ProcessingComplete和ProcessingFailed事件。我有事件处理程序与这些事件挂钩:

  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(成功地)!;
}
else
{
Debug.WriteLine(无法处理项!);
}
}

我想做的是让我的代码在调用3rdPartyLibObject.Process()之后,直到其中一个事件处理程序触发,所以我知道项目是否无法进行处理(以及是否将其从列表中删除)。我猜这可能不是一个罕见的情况,但我从来没有遇到过。有一个普遍同意的最佳做法来处理这种情况?

解决方案

个人来说,我会把它包装成一个任务< bool> ,如下所示:

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

thirdParty.ProcessingComplete + =(o,e)=> tcs.SetResult(真);
thirdParty.ProcessingFailed + =(o,e)=> tcs.SetResult(假);

thirdParty.Process(item);

return tcs.Task;
}

您可以这样调用:

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

如果您以后决定要异步运行或处理多个项目一次(如果第三方库支持这个),这也是非常简单的转移到C#5的异步/等待支持,使整个事情是异步的。


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?

解决方案

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.

这篇关于阻止代码并等待事件处理程序触发?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆