我正在编写一个使用第三方库来处理某些数据的应用程序。在一个非常简单的例子中,我有一个像这样的任务运行的方法:
private void ProcessListOfItems(List<string> items)
{
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("Item was processed succesfully!");
}
else
{
Debug.WriteLine("Failed to process item!");
}
}
我想要做的是在调用3rdPartyLibObject.Process()之后立即使用我的代码块,直到其中一个事件处理程序触发,因此我知道项目是否处理失败(以及是否应该删除它是从列表中还是没有)。我猜这可能不是一个不寻常的情况,但我以前从未遇到过这种情况。是否有一个普遍认同的最佳做法来处理这种情况?
答案 0 :(得分:12)
就个人而言,我会将其包装成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的异步/等待支持,以使整个事物异步。
答案 1 :(得分: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;
}
假设事件在同一个线程上全部触发,则在处理下一个项目之前应该调用处理程序。