Проблема с Timout HttpClient c#
При отправки запроса на rest веб сайта тяжелого файла упирался в ошибку таймаута "The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing."
Исправил данным образом:
public static HttpClient _client = HttpClientGenerator(20);
private static HttpClient HttpClientGenerator(int TimeOut)
{
HttpClientHandler handler = new HttpClientHandler();
var httpClient = new HttpClient(handler,false);
httpClient.Timeout = TimeSpan.FromMinutes(TimeOut);
return httpClient;
}
Но, такой большой таймаут не нужен хочу определять его от размера файла
if (MB < 500)
_client = HttpClientGenerator(10);
else if (MB < 14000)
_client = HttpClientGenerator(20);
else
_client = HttpClientGenerator(30);
Проблема в том что появляется ошибка - System.Net.Http.HttpRequestException: "An error occurred while sending the request."
InvalidOperationException: Вызывающий поток не может получить доступ к данному объекту, так как владельцем этого объекта является другой поток.
Как можно исправить данную проблему?
Добавление к ответу:Изначально это исключение было создано в этом стеке вызовов: [Внешний код] App.Resources.Net.Rest_API.RestService.E24SendFileBase.AnonymousMethod__0(int) в RestService.cs App.Resources.Net.Rest_API.ProgressStreamContent.SerializeToStreamAsync(System.IO.Stream, System.Net.TransportContext) в ProgressStreamContent.cs [Внешний код]
Метод который отправляет данные на веб ресурс:
public static async Task<string> E24SendFileBase(string file, string fileName, ProgressBar progressBar, System.Windows.Controls.Label label) а
{
using (var content = new MultipartFormDataContent())
{
var progressContent = new ProgressStreamContent(new StreamContent(System.IO.File.OpenRead(file)), progress: progress =>
{
progressBar.Value = progress;
label.Content = $"{progress} %";
}, totalBytesRead: totalBytesRead =>
{
label.Content += $" {totalBytesRead} /";
}, totalBytes: totalBytes =>
{
label.Content += $" {totalBytes}";
});
switch (fileName.Remove(0, fileName.IndexOf(".") + 1))
{
case "zip":
progressContent.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/zip");
break;
case "dt":
progressContent.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/octet-stream");
break;
case "1CD":
progressContent.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/octet-stream");
break;
default:
break;
}
ulong MB = Convert.ToUInt64(progressContent.Headers.ContentLength) >> 20;
/*if (MB < 500)
_client = HttpClientGenerator(10);
else if (MB < 14000)
_client = HttpClientGenerator(20);
else
_client = HttpClientGenerator(30);*/
content.Add(progressContent, name: "FILE_BASE", fileName: $"{fileName}");
using (var message = await _client.PostAsync("https://fake/rest//fake/", content))
{
return message.Content.ReadAsStringAsync().Result;
}
}
Класс ProgressStreamContent
public class ProgressStreamContent : HttpContent
{
private readonly HttpContent _content;
private readonly Action<int> _progress;
private readonly Action<string> _totalBytesRead;
private readonly Action<string> _totalBytes;
public ProgressStreamContent(HttpContent content, Action<int> progress, Action<string> totalBytesRead, Action<string> totalBytes)
{
_content = content;
_progress = progress;
_totalBytesRead = totalBytesRead;
_totalBytes = totalBytes;
}
protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
var buffer = new byte[4096];
var totalBytesRead = 0L;
using (var inputStream = await _content.ReadAsStreamAsync())
{
var totalBytes = inputStream.Length;
var bytesRead = 0;
while ((bytesRead = await inputStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await stream.WriteAsync(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
var progress = (int)((double)totalBytesRead / totalBytes * 100);
_progress(progress);
_totalBytesRead(SizeSuffix(totalBytesRead));
_totalBytes(SizeSuffix(totalBytes));
}
}
}
protected override bool TryComputeLength(out long length)
{
length = _content.Headers.ContentLength.GetValueOrDefault();
return true;
}
static readonly string[] SizeSuffixes =
{ "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
static string SizeSuffix(Int64 value, int decimalPlaces = 1)
{
if (value < 0) { return "-" + SizeSuffix(-value, decimalPlaces); }
int i = 0;
decimal dValue = (decimal)value;
while (Math.Round(dValue, decimalPlaces) >= 1000)
{
dValue /= 1024;
i++;
}
return string.Format("{0:n" + decimalPlaces + "} {1}", dValue, SizeSuffixes[i]);
}
}