У меня есть .NET Framework приложение Windows Forms с формой, имеющей этот код:
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace test
{
public partial class Main : Form
{
public int exitCode = 1;
private Options opts;
CancellationTokenSource cancellationSource = new CancellationTokenSource();
public Main(Options opts)
{
InitializeComponent();
this.opts = opts;
}
private void btnCancel_Click(object sender, EventArgs e)
{
exitCode = 1;
cancellationSource.Cancel();
Close();
}
async Task doUpload()
{
using (var content = new MultipartFormDataContent())
{
List<FileStream> streams = new List<FileStream>();
try
{
foreach (string fPath in opts.InputFiles)
{
FileStream stream = new FileStream(fPath, FileMode.Open, FileAccess.Read);
streams.Add(stream);
content.Add(new StreamContent(stream), fPath);
}
var progressContent = new ProgressableStreamContent(
content,
4096,
(sent, total) =>
{
double percent = 100 * sent / total;
progressBar.Value = (int)percent;
});
using (var client = new HttpClient())
{
using (var response = await client.PostAsync(opts.URL, progressContent, cancellationSource.Token))
{
if (response.IsSuccessStatusCode)
{
exitCode = 0;
}
else
{
MessageBox.Show(
response.Content.ToString(),
"Error " + response.StatusCode,
MessageBoxButtons.OK, MessageBoxIcon.Error
);
}
Close();
}
}
}
finally
{
foreach (FileStream stream in streams)
{
stream.Close();
}
}
}
}
private void Main_Load(object sender, EventArgs e)
{
}
private void Main_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = !cancellationSource.IsCancellationRequested;
}
private void Main_Shown(object sender, EventArgs e)
{
doUpload();
}
}
}
ProgressableStreamContent такой же, как здесь: C #: HttpClient, прогресс загрузки файла призагрузка нескольких файлов как MultipartFormDataContent
Проблема заключается в том, что ответ никогда не возвращается. Другими словами: ожидание postAsync никогда не завершается. Кроме того, обратный вызов прогресса никогда не перезванивается. Даже если я попытаюсь использовать POST-URL, который содержит нерасходный домен, ничего не происходит. Я думаю, это тупик, но я не понимаю, как? Результат асинхронной задачи никогда нигде не используется и не ожидается.
Он отличается от Пример асинхронного ожидания / ожидания, который вызывает взаимоблокировку , поскольку .Result не используется, а методникогда не ожидал, а также кажется, что вызов ConfigureAwait (false) не имеет никакого эффекта.
ОБНОВЛЕНИЕ : я создал новое репозиторий github для этого вопроса, поэтому любой может его проверить:
https://github.com/nagylzs/csharp_http_post_example
ОБНОВЛЕНИЕ : Наконец-то все работает. ConfigureAwait не нужен. Все операции обновления пользовательского интерфейса должны быть помещены в Invoke. Я обновил тестовое репо до рабочей версии. Также добавлена поддержка TLSv1.2 (которая по умолчанию отключена).