У меня есть метод, который загружает файл по TCP-соединению, и я хочу отобразить на консоли индикатор завершения загрузки.
В настоящее время я использую метод, который вызывает события для отображения индикатора выполнения и его обновления.
Моя проблема в том, что дисплей не асинхронный, и он сильно замедляет процесс загрузки. Я пытался обрабатывать события с помощью Задач, но не смог получить хороший результат, так как несколько потоков одновременно обновляли бы индикатор выполнения, и это приводило к беспорядку.
Способ загрузки:
public void DownloadFile(Stream stream)
{
if (!stream.CanWrite)
{
// The stream can't be written : invalid argument
throw new ArgumentException();
}
// Get the data lenght first
var dataLength = long.Parse(ReadLine());
// Send ready flag
WriteLine("{OK}");
var buffer = new byte[DEFAULT_BUFFER_SIZE];
long bytesWritten = 0;
try
{
// Notify that the stream transfert started if the handler has been implemented
StreamTransfertStartEvent?.Invoke(dataLength);
int bytesRead;
while ((bytesRead = binaryReader.Read(buffer, 0, buffer.Length)) > 0)
{
stream.Write(buffer, 0, bytesRead);
bytesWritten += bytesRead;
// Notify that the stream transfert progress changed if the handler has been implemented
StreamTransfertProgressEvent?.Invoke(bytesWritten);
// The file has been totally written
if (bytesWritten == dataLength)
{
break;
}
}
}
catch (Exception)
{
StreamTransfertFailEvent?.Invoke();
throw new NetworkException();
}
}
Вы можете увидеть в коде выше 3 события, которые я использую для обновления индикатора выполнения:
- StreamTransfertStartEvent
- StreamTransfertProgressEvent
- StreamTransfertFailEvent
А для кода обновления индикатора выполнения (только код, вызываемый обработчиком StreamTransfertProgressEvent):
public static void Update(long current)
{
var newCompletion = (int)((decimal)current / total * 100);
// Transfert progressed
if (completion != newCompletion)
{
completion = newCompletion;
if (completion % 2 == 0)
{
Console.SetCursorPosition(1, lastLine - 1);
Console.Write(new string('=', completion / 2 - 1));
Console.Write('>');
}
var leftStart = 52 - total.ToString().Length - 7 - current.ToString().Length;
Console.SetCursorPosition(leftStart, lastLine);
Console.Write(current);
// Transfert finished
if (completion == 100)
{
Console.SetCursorPosition(50, lastLine - 1);
Console.Write('=');
End();
}
}
}