2012-10-15 92 views
2

我正在编写使用第三方库处理某些数据的应用程序。在非常简单的例子,我有运行作为这样的任务的方法:阻止代码并等待事件处理程序触发?

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

正如你看到的,我的代码目前正在编写方式,我从列表中尽快删除每个项目的工艺路线()方法返回。但是,某件物品的处理可能会失败,我需要知道这是否会发生。不幸的是,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("Item was processed succesfully!"); 
    } 
    else 
    { 
     Debug.WriteLine("Failed to process item!"); 
    } 
} 

我想什么做的是有我的代码块中调用3rdPartyLibObject.Process(后右),直至事件处理程序火灾这样的一个我知道该项目是否无法处理(以及我是否应该从列表中删除它)。我猜这可能不是一个不常见的情况,但我从来没有遇到过它。处理这种情况有没有普遍认同的最佳做法?

+0

为什么不将您的物品删除代码添加到OnProcessed方法中?显然这需要跟踪哪个项目正在处理,但这是我能看到的最简单的解决方案。 –

+0

班上的布尔场无法解决。 –

回答

11

个人而言,我把这个包成Task<bool>,像这样:

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; 
} 

然后,您可以调用这个像这样:

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的异步/等待支持以使整个事物异步来说也是非常简单的。

+0

难道你不想使用'TrySetResult'而不是'SetResult',因为两者之一会失败。 – Servy

+0

@Servy如果两个中只有一个会被调用(这是OP建议的),那么'SetResult'应该没问题。如果两个事件都可能发生在同一个实例上,那么'TrySetResult'会更好。 –

+0

@ReedCopsey如何将此模式重构为异步/等待C#5? – Arvis

1

将这项工作:

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; 
} 

假设事件在同一线程上的所有火,处理应该处理你的下一个项目之前调用。

+1

感谢您的建议!尽管我最终选择了另一个答案来解答我的问题,但我很欣赏你的想法以及你提出建议的时间! – user685869

相关问题