3

サードパーティのライブラリを使用してデータを処理するアプリケーションを作成しています。非常に単純化された例では、次のようなタスクとして実行されるメソッドがあります。

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() への呼び出しの直後から、イベント ハンドラーの 1 つが起動するまで、コード ブロックを保持することです。リストかどうか)。これはおそらく珍しい状況ではないと思いますが、これまでに遭遇したことはありません。この種のシナリオに対処するための一般的に合意されたベスト プラクティスはありますか?

4

2 に答える 2

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 の async/await サポートに移行して、全体を非同期にするのも非常に簡単です。

于 2012-10-15T17:15:59.660 に答える
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;
}

イベントがすべて同じスレッドで発生すると仮定すると、次のアイテムを処理する前にハンドラーを呼び出す必要があります。

于 2012-10-15T17:18:15.853 に答える