他写了一个用于持续写入log的工具类。用到异步锁,目的是保证上次异步写完,后面再写,否则前面没写入,后面又调用要写入,.NET就会抛出IOException了
[C#] 纯文本查看 复制代码 public class LogAsyncWriter
{
private readonly SemaphoreSlim _Semaphore = new SemaphoreSlim(1, 1);
private readonly StreamWriter _StreamWriter;
public LogAsyncWriter(string filePath)
{
_StreamWriter = new StreamWriter(filePath, true, Encoding.UTF8);
}
public LogAsyncWriter(string filePath, Encoding encoding)
{
_StreamWriter = new StreamWriter(filePath, true, encoding);
}
public async Task WriteLogAsync(string logText, bool isAppendLine = true)
{
await _Semaphore.WaitAsync();
try
{
if (isAppendLine == true)
await _StreamWriter.WriteLineAsync(logText);
else
await _StreamWriter.WriteAsync(logText);
}
finally
{
_Semaphore.Release();
}
}
public async Task CloseAsync()
{
await _Semaphore.WaitAsync();
try
{
_StreamWriter.Flush();
_StreamWriter.Close();
}
finally
{
_Semaphore.Release();
}
}
}
然后他又写了一个测试代码,在Form中点击一个按钮的事件
[C#] 纯文本查看 复制代码 private LogAsyncWriter _LogAsyncWriter;
private string _OnceWriteText;
private void BtnTestLogAsyncWriter_Click(object sender, EventArgs e)
{
_LogAsyncWriter = new LogAsyncWriter(@"D:\TestLogAsyncWriter.txt");
StringBuilder lotsOfTextSB = new StringBuilder();
for (int i = 0; i < 2048; i++)
lotsOfTextSB.Append("a");
_OnceWriteText = lotsOfTextSB.ToString();
UIUtil.AppendTextToRichTextBox(RtxConsole, $"[{DateTime.Now.ToString("HH:mm:ss")}]准备写入Log");
_StartWriteLog();
// 做其他事情
UIUtil.AppendTextToRichTextBox(RtxConsole, $"[{DateTime.Now.ToString("HH:mm:ss")}]运行到后续代码");
}
private async void _StartWriteLog()
{
// 连续3秒写入大量内容
DateTime endTime = DateTime.Now.AddSeconds(3);
int writeCount = 0;
while (DateTime.Now < endTime)
{
await _LogAsyncWriter.WriteLogAsync(_OnceWriteText);
writeCount++;
}
AppendTextToRichTextBox(RtxConsole, $"[{DateTime.Now.ToString("HH:mm:ss")}]完成3秒的写入,共写入{writeCount}次");
await _LogAsyncWriter.CloseAsync();
AppendTextToRichTextBox(RtxConsole, $"[{DateTime.Now.ToString("HH:mm:ss")}]完成文件关闭");
}
public static void AppendTextToRichTextBox(RichTextBox rtx, string text, bool isAppendNewLine = true)
{
// 让富文本框获取焦点
rtx.Focus();
// 设置光标的位置到文本结尾
rtx.Select(rtx.TextLength, 0);
// 滚动到富文本框光标处
rtx.ScrollToCaret();
// 追加内容
rtx.AppendText(text);
// 换行
if (isAppendNewLine == true)
rtx.AppendText(Environment.NewLine);
// 刷新UI
rtx.Refresh();
}
但是发现,在点击按钮,3秒持续写入过程中,整个form界面都是卡死的,他不明白这是为什么。以下是它提问的原话:
_StartWriteLog是异步方法,我在button点击事件中,并没有await 这个函数,而运行看,也确实在开始时候,就已经打印出:“运行到后续代码”,说明确实没有阻塞。但是winfrom界面为什么会卡呢? |