Здравствуйте, уважаемые коллеги, мне нужно сохранять в текстовый файл каждый раз, когда я получаю новое сообщение с моего последовательного порта на свой RichTextBox
. Я пытаюсь использовать async
и await
, он не блокирует пользовательский интерфейс при сохранении текстового файла, но, к сожалению, я делаю что-то не так, потому что он все еще блокируется. Пожалуйста, что я делаю не так?
TextChanged
обработчик событий от RichTextBox
:
private async void rtb_msg_TextChanged(object sender, EventArgs e)
{
btn_save.Enabled = true;
rtb_msg.ScrollToCaret();
rcvFlag = true;
await SaveFile();
}
Асинхронный SaveFile
метод:
private async Task SaveFile()
{
if (_serialPort.BytesToRead == 0 && rcvFlag == true)
{
for(int i = 0; i < 10; i++)
{
Thread.Sleep(1000);
}
using (StreamWriter writer = new StreamWriter(reportFolder + reportFile))
{
await writer.WriteAsync(rtb_msg.Text);
}
rcvFlag = false;
}
}
Служит ли Thread.Sleep(1000)
заполнителем для фактического длительного вызова метода?
Эта часть определенно заблокирует ваш поток пользовательского интерфейса:
for(int i = 0; i < 10; i++)
{
Thread.Sleep(1000);
}
Не уверен, почему он там, но если вы замените его асинхронной версией, он должен работать:
for(int i = 0; i < 10; i++)
{
await Task.Delay(1000);
}
Никогда не используйте Thread.Sleep
в асинхронных методах. Вместо этого используйте Task.Delay
и Task.Run
private Task SaveFileAsync()
{
return Task.Run(async () =>
{
if (_serialPort.BytesToRead == 0 && rcvFlag == true)
{
for (var i = 0; i < 10; i++)
{
await Task.Delay(1000);
}
using (var writer = new StreamWriter(reportFolder + reportFile))
{
await writer.WriteAsync(rtb_msg.Text);
}
rcvFlag = false;
}
});
}
+1 за возможность выполнить Task.Run. Но имейте в виду, что это имеет смысл только тогда, когда у вас много работы, связанной с процессором, например, огромные вычисления. Что здесь, похоже, не так.
@Stefan the Task.Run
также имеет смысл для работы, связанной с вводом-выводом, для которой не существует асинхронного API. В некоторых случаях может быть даже предпочтительнее использовать Task.Run
вместо существующего асинхронного API, поскольку соответствующий синхронный API более производительный.
@TheodorZoulias: да, это совершенно правильно, я упростил.
Асинхронный! = Многопоточность