C# HttpWebRequest 问题:基础连接已关闭:发送时发生意外错误

C# HttpWebRequest issue: The underlying connection was closed: An unexpected error occurred on a send

提问人:J.Tran 提问时间:6/1/2023 最后编辑:BhuvaneshwaranJ.Tran 更新时间:6/1/2023 访问量:107

问:

我正在制作一个 winforms 应用程序,我想同时向我的 Https API url 发送多个(比如 20-30 个请求),并且请求总数不受限制。但是,在随机时间之后,我的应用程序遇到了问题HttpWebRequestWinforms

error: The underlying connection was closed: An unexpected error occurred on a send

我应该更改代码的哪些部分,以使我的应用正确高效地运行,并毫无问题地发送多个请求HttpWebRequest

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
_tasks = new List<Task>();
cancelSources = new List<CancellationTokenSource>();

foreach (var emailList in smalChunks)
{
    CancellationTokenSource cs = new CancellationTokenSource();
    Task task = Task.Run(async () =>
    {
        await HandleEmailList(emailList, userData, cs);
    }, cs.Token);

    _tasks.Add(task);
    cancelSources.Add(cs);
}
await Task.WhenAll(_tasks.ToArray()).ConfigureAwait(false);

功能波纹管手柄HttpWebRequest

private async Task HandleEmailList(List<SorterResults> emailList, CancellationTokenSource cs)
{
    try
    {
        ar sortUrl = $"http://localhost:5000/api/xxx";

        var httpWebRequest = (HttpWebRequest)WebRequest.Create(sortUrl);
        httpWebRequest.ContentType = "application/json";
        httpWebRequest.Method = "POST";

        using (var streamWriter = new StreamWriter(await httpWebRequest.GetRequestStreamAsync()))
        {
            var jsonData = JsonConvert.SerializeObject(emailList.ToArray());
            var mailData = $"{{\"mails\":{jsonData}}}";
            await streamWriter.WriteAsync(mailData);
        }

        APIResponseData responseResult;
        var httpResponse = (HttpWebResponse)(await httpWebRequest.GetResponseAsync());
        using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
        {
            var result = await streamReader.ReadToEndAsync();
            responseResult = JsonConvert.DeserializeObject<APIResponseData>(result);
        }
                
        cs.Token.ThrowIfCancellationRequested();
    }
    catch (Exception ex)
    {
        //ex.Message: The underlying connection was closed: An unexpected error occurred on a send
    }
}
C# 多线程 WinForms 并发 httpWebRequest

评论


答:

1赞 Andy Wynn 6/1/2023 #1

您能否确认内部任务是否运行? 在这一行上粘贴一个断点,看看它是否被命中:

cs.Token.ThrowIfCancellationRequested() 

我怀疑这可能是当您的使用块处理流编写器时,它也会处理流并关闭连接。我会更改 Visual Studio 中的异常设置以中断任何异常类型,然后您可以进一步询问这一点。

另外,请告诉我您不是在构建电子邮件僵尸网络!

以下是一些额外的不请自来的建议:

当方法采用 时不要调用,它作为列表很好,并且该转换只会减慢您的应用程序速度_tasks.ToArray()IEnumerable

为什么要创建多个对象?你能只创建一个,然后把令牌传下来吗?CancellationTokenSource

为什么要使用匿名委托转发任务?你有一个返回任务的函数,所以你不能把它添加到列表中吗?Task.Run

通过以下更改:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
_tasks = new List<Task>();
CancellationTokenSource cs = new CancellationTokenSource();
    
foreach (var emailList in smalChunks)
{
    Task task = HandleEmailList(emailList, userData, cs);
    _tasks.Add(task);
}
await Task.WhenAll(_tasks).ConfigureAwait(false);

同时更改任务函数的签名

private async Task HandleEmailList(List<SorterResults> emailList, CancellationToken ct)

评论

1赞 J.Tran 6/1/2023
我正在制作邮件分拣机。我改用 ,它运行良好。感谢您的代码反思。HttpClient