简体   繁体   English

C#多个异步HttpRequest带有一个回调

[英]C# multiple asynchronous HttpRequest with one callback

I want to make 10 asynchronous http requests at once and only process the results when all have completed and in a single callback function. 我想一次发出10个异步http请求,只在完成所有结果并在单个回调函数中处理结果。 I also do not want to block any threads using WaitAll (it is my understanding that WaitAll blocks until all are complete). 我也不想使用WaitAll来阻止任何线程(我理解WaitAll会阻塞所有线程直到完成)。 I think I want to make a custom IAsyncResult which will handle multiple calls. 我想我想制作一个可以处理多个调用的自定义IAsyncResult。 Am I on the right track? 我是在正确的轨道上吗? Are there any good resources or examples out there that describe handling this? 是否有任何好的资源或示例描述处理此问题?

I like Darin's solution. 我喜欢达林的解决方案。 But, if you want something more traditional, you can try this. 但是,如果你想要更传统的东西,你可以试试这个。

I would definitely use an array of wait handles and the WaitAll mechanism: 我肯定会使用一组等待句柄和WaitAll机制:

static void Main(string[] args)
{

    WaitCallback del = state =>
    {
        ManualResetEvent[] resetEvents = new ManualResetEvent[10];
        WebClient[] clients = new WebClient[10];

        Console.WriteLine("Starting requests");
        for (int index = 0; index < 10; index++)
        {
            resetEvents[index] = new ManualResetEvent(false);
            clients[index] = new WebClient();

            clients[index].OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);

            clients[index].OpenReadAsync(new Uri(@"http:\\www.google.com"), resetEvents[index]);
        }

        bool succeeded = ManualResetEvent.WaitAll(resetEvents, 10000);
        Complete(succeeded);

        for (int index = 0; index < 10; index++)
        {
            resetEvents[index].Dispose();
            clients[index].Dispose();
        }
    };

    ThreadPool.QueueUserWorkItem(del);

    Console.WriteLine("Waiting...");
    Console.ReadKey();
}

static void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
    // Do something with data...Then close the stream
    e.Result.Close();

    ManualResetEvent readCompletedEvent = (ManualResetEvent)e.UserState;
    readCompletedEvent.Set();
    Console.WriteLine("Received callback");
}


static void Complete(bool succeeded)
{
    if (succeeded)
    {
        Console.WriteLine("Yeah!");
    }
    else
    {
        Console.WriteLine("Boohoo!");
    }
}

In .NET 4.0 there's a nice parallel Task library that allows you to do things like: 在.NET 4.0中,有一个很好的并行任务库 ,允许您执行以下操作:

using System;
using System.Linq;
using System.Net;
using System.Threading.Tasks;

class Program
{
    public static void Main()
    {
        var urls = new[] { "http://www.google.com", "http://www.yahoo.com" };

        Task.Factory.ContinueWhenAll(
            urls.Select(url => Task.Factory.StartNew(u => 
            {
                using (var client = new WebClient())
                {
                    return client.DownloadString((string)u);
                }
            }, url)).ToArray(), 
            tasks =>
            {
                var results = tasks.Select(t => t.Result);
                foreach (var html in results)
                {
                    Console.WriteLine(html);
                }
        });
        Console.ReadLine();
    }
}

As you can see for each url in the list a different task is started and once all tasks are completed the callback is invoked and passed the result of all tasks. 正如您可以在列表中看到的每个URL一样,启​​动了一个不同的任务,一旦完成所有任务,就会调用回调并传递所有任务的结果。

I think you are better off using the WaitAll approach. 我认为你最好使用WaitAll方法。 Otherwise you will be processing 10 IAsyncResult callbacks, and using a semaphore to determine that all 10 are finally complete. 否则,您将处理10个IAsyncResult回调,并使用信号量确定所有10个最终完成。

Keep in mind that WaitAll is very efficient; 请记住,WaitAll效率很高; it is not like the silliness of having a thread "sleep." 它不像是一个线程“睡觉”的愚蠢。 When a thread sleeps, it continues to use processing time. 线程休眠时,它会继续使用处理时间。 When a thread is "de-scheduled" because it hit a WaitAll, then the thread no longer consumes any processor time. 当一个线程被“取消调度”,因为它击中了WaitAll,那么该线程不再消耗任何处理器时间。 It is very efficient. 它非常有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM