在异步事件上写入控制台

Writing to Console on async event

我正在使用 WebClient 向服务器提交一组 HTTP 请求(顺序无关紧要)。

我不想发送请求,而是等待、发送、等待等等。我想发送尽可能多的请求,然后等待响应的到来,但是,当我需要写入控制台时,问题就出现了在特定请求完成后。

输出看起来不错,然后我开始收到多个请求消息,然后是一组 Responses/Errors,而不是请求消息后跟响应。

在每个块完成之前,是否有任何方法可以阻止任何其他控制台写入?

int currentRequest = 1;
for (int i = 0; i < requests.Count; i++) {
    using (var webclient = new WebClient())
    {
        webclient.DownloadStringCompleted += (sender, e) =>
        {
            Console.WriteLine();
            Info("Request: " + currentRequest + "/" + requests.Count);
            if (e.Error == null) {
                // Do something with e.Result
            } else {
                Console.WriteLine("Error: " + e.Error.Message);
            }
            currentRequest += 1;
        };
        webclient.DownloadStringAsync(new Uri("URL HERE"));
    }
}

另一个注意事项:我觉得这不是我应该处理请求的方式(异步),如果我错了请纠正我。

Is there any way to block any other Console Writes until each block finishes?

是的,这就是 lock 的目的。

int currentRequest = 1;
Object lockObject = new Object();
for (int i = 0; i < requests.Count; i++) {
    using (var webclient = new WebClient())
    {
        webclient.DownloadStringCompleted += (sender, e) =>
        {
            lock(lockObject) 
            {
               Console.WriteLine();
               ...                
               currentRequest += 1;
            }
        };
        webclient.DownloadStringAsync(new Uri("URL HERE"));
    }
}

严格来说这不会阻塞其他 'console writes',但它确实序列化了每个响应的处理。

I don't feel like this is how I should be handling requests (asynchronously)

没错。您应该使用 await, Task and Parallel.ForEach. I'm not going to write a full example because for handling URLS, there are way way way more complications than just the async. I recommend you also read about ServicePointManager.DefaultConnectionLimit 并理解为什么您的异步下载可能比您预期的要慢。