0

実行時にタスクのリストを実行しようとしています。これを非同期操作にしたい。各タスクは Web サービスを呼び出し、リストに追加する応答を返します。すべての操作が完了したら、すべてを 1 つのドキュメントにマージします。

これが私のコードです。現在、同期呼び出しのみとして実行されています。一度に撃ってもらいたい。

List<XmlDocument> XmlResponse = new List<XmlDocument>();
XmlDocument xDocument = new XmlDocument();
ServiceRequest service = GetServiceRequest();
var tasks = new List<Task>();

Parallel.ForEach(service.IRN, x => 
{
    tasks.Add(Task.Factory.StartNew(() =>
    {
        XmlDocument xRequest = BuildServiceRequest(
            new ServiceRequest 
            {
                AccountNumber = service.AccountNumber, 
                MemberId = service.MemberId, 
                IRN = new List<string> { x }
            });
        Debug.Print("Service Call " + DateTime.Now.ToString("hh.mm.ss.ffffff"));
        XmlDocument xResponse = WebRequest.Submit(xRequest); // This is invoking service
        XmlResponse.Add(xResponse);
    }));
});

try
{
    Task.WaitAll(tasks.Where(x => x != null).ToArray());
    xDocument = PrepareServiceResponse();
    Debug.Print("Task Ends" + DateTime.Now.ToString("hh.mm.ss.ffffff"));
}

ここでこのコードを実行すると、サービスが同期的に呼び出されます。タスクリストで一度にすべての通話を撃つ方法を誰か提案できますか?

4

1 に答える 1

3

Parallel ForEach ループ内で大量のタスクを作成しているようです。Parallel.ForEach がタスクの作成を処理するため、これを行う必要はありません。

Parallel.ForEach(service.IRN, x => 
{
    XmlDocument xRequest = BuildServiceRequest(
       new ServiceRequest 
        {
            AccountNumber = service.AccountNumber, 
            MemberId = service.MemberId, 
            IRN = new List<string> { x }
        });
    Debug.Print("Service Call " + DateTime.Now.ToString("hh.mm.ss.ffffff"));
    XmlDocument xResponse = WebRequest.Submit(xRequest); 
    XmlResponse.Add(xResponse);
});

それはそれを行う必要があります。次の行に到達すると、すべてのタスクが完了します。ただし、実行する呼び出しの数、使用されるスレッドの数、および各呼び出しにかかる時間によっては、応答が IRN 文字列と同じ順序になるという保証はありません。

余談ですが、リストに追加するとエラーが発生する場合があります。別の解決策については、次の 2 つの質問を参照してください: Parallel.ForEach() を使用して新しい要素をリストに追加できますか? またはParallel.ForEach() スレッドセーフのこの使用はありますか?

于 2013-10-23T12:39:42.333 に答える