gpt4 book ai didi

c# - Task.WaitAll() 在控制台应用程序中挂起

转载 作者:行者123 更新时间:2023-11-30 23:14:08 29 4
gpt4 key购买 nike

我有一个控制台应用程序,我需要在其中从 4 个不同的站点检索一些数据。我将每个 HTTP 请求放在一个任务中,然后等待它们全部完成。

当我只需要从 2 个站点获取数据时,它就可以正常工作。但后来我需要添加其他数据源,当添加 3 个或更多请求时,Task.WaitAll() 挂起。

下面是我的代码。

我最终使用 Task.WaitAll() 的原因是因为我需要停止并防止控制台应用程序退出 - 即我需要在所有 HTTP 请求返回数据后才执行其他任务。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
class Program
{
static Task[] tasks = new Task[3];

static void Main(string[] args)
{
try
{
Run();
}
catch (System.Exception ex)
{

}
}

public static async void Run()
{
//works when using one or two tasks
tasks[0] = HttpExtensions.GetMyData("http://www.w3.org/TR/PNG/iso_8859-1.txt");
tasks[1] = HttpExtensions.GetMyData("http://www.w3.org/TR/PNG/iso_8859-1.txt");

//fails when add 3 or more task
tasks[2] = HttpExtensions.GetMyData("http://www.w3.org/TR/PNG/iso_8859-1.txt");
//tasks[3] = HttpExtensions.GetMyData("http://www.w3.org/TR/PNG/iso_8859-1.txt");

Task.WaitAll(tasks);

var result4 = ((Task<Stream>)tasks[2]).Result;

}
}

public static class HttpExtensions
{
public static Stopwatch sw;
public static long http_ticks = 0;

public static Task<HttpWebResponse> GetResponseAsync(this HttpWebRequest request)
{
var taskComplete = new TaskCompletionSource<HttpWebResponse>();
request.BeginGetResponse(asyncResponse =>
{
try
{
HttpWebRequest responseRequest = (HttpWebRequest)asyncResponse.AsyncState;
HttpWebResponse someResponse = (HttpWebResponse)responseRequest.EndGetResponse(asyncResponse);
taskComplete.TrySetResult(someResponse);
}
catch (WebException webExc)
{
HttpWebResponse failedResponse = (HttpWebResponse)webExc.Response;
taskComplete.TrySetResult(failedResponse);
}
}, request);
return taskComplete.Task;
}


public static async Task<Stream> GetMyData(string urlToCall)
{

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(urlToCall);
request.Method = HttpMethod.Get;
HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync();
//using (var sr = new StreamReader(response.GetResponseStream()))
//{

return response.GetResponseStream();
//}
}

}

public static class HttpMethod
{
public static string Head { get { return "HEAD"; } }
public static string Post { get { return "POST"; } }
public static string Put { get { return "PUT"; } }
public static string Get { get { return "GET"; } }
public static string Delete { get { return "DELETE"; } }
public static string Trace { get { return "TRACE"; } }
public static string Options { get { return "OPTIONS"; } }
public static string Connect { get { return "CONNECT"; } }
public static string Patch { get { return "PATCH"; } }
}
}

最佳答案

有很多问题。

首先,正如我在上面的评论中提到的,不返回 Task您或多或少挂起了您的应用程序,因为它无法判断任务何时完成。

但是,一旦您更改了 Run()返回任务的方法,您需要通过 Task.Run 调用在 Main 中调用它方法。

其次,您使用 WebClient 使代码过于复杂。切换到 HttpClient 并利用其自然的异步/等待 API。

第三,您实际上并没有在等待 Run() 中的任何内容。方法,因此将其更改为任务不会执行任何操作,因为您没有等待导致它同步运行的结果(没有双关语意)。更新您的方法以等待结果。

最后,WaitAll阻塞线程,这可能不是你想要的。您可以使用 WhenAll相反,等待该调用,允许您的应用程序在您的任务运行时释放线程。

下面是我推荐修改的一个完整的工作示例,经过简化以显示一个工作程序。 Main 方法推荐取自 https://social.msdn.microsoft.com/Forums/vstudio/en-US/fe9acdfc-66cd-4b43-9460-a8053ca51885/using-new-asyncawait-in-console-app?forum=netfxbcl

class Program
{
static Task[] tasks = new Task[3];
static HttpClient _client = new HttpClient();

static void Main(string[] args)
{
Console.WriteLine("Main start");
Task t = Run();
t.ContinueWith((str) =>
{
Console.WriteLine(str.Status.ToString());
Console.WriteLine("Main end");
});
t.Wait();
}

public static async Task Run()
{
tasks[0] = GetMyData("http://www.w3.org/TR/PNG/iso_8859-1.txt");
tasks[1] = GetMyData("http://www.w3.org/TR/PNG/iso_8859-1.txt");
tasks[2] = GetMyData("http://www.w3.org/TR/PNG/iso_8859-1.txt");

await Task.WhenAll(tasks);

var result4 = (await (Task<Stream>)tasks[2]);
}

public static async Task<Stream> GetMyData(string urlToCall)
{
return await _client.GetStreamAsync(urlToCall);
}
}

关于c# - Task.WaitAll() 在控制台应用程序中挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43302017/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com