我正在创建类似于类的流,它继承自Stream
。当我使用StreamWriter
类异步写入信息时:
using (var sw = new StreamWriter(messageWriter, Encoding.UTF8))
await sw.WriteAsync(msg);
我可以看到StreamWriter
直接转到void Stream.Write(byte[] buffer, int offset, int count)
而不是Task Stream.WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
。
这是一个错误还是我错过了什么?
答案 0 :(得分:7)
我发现了混乱的根源。
除非您专门异步刷新,否则 StreamWriter
默认情况下会同步刷新。
Stream.Flush
,当然还会刷新。
这将在Write
信息流中调用WriteAsync
而不是messageWriter
:
using (var sw = new StreamWriter(messageWriter, Encoding.UTF8))
await sw.WriteAsync("Hi");
StreamWriter
将缓冲“Hi”消息,并在关闭Flush
时同步释放到StreamWriter
调用的基础流。
因此对StreamWriter.WriteAsync
的异步调用可能对底层流没有影响(因为缓冲),并且在调用StreamWriter.Close
时,同步调用StreamWriter.Flush
,因此{{ 1}}基础流上的方法。
此代码也同步调用Flush
:
Write
显然也是这个:
using (var sw = new StreamWriter(messageWriter, Encoding.UTF8))
{
sw.AutoFlush = true; // will call Write here to send the UTF8 BOM
await sw.WriteAsync("Hi"); // Write the actual data
}
这将调用using (var sw = new StreamWriter(messageWriter, Encoding.UTF8))
{
await sw.WriteAsync("Hi");
sw.Flush();
}
:
WriteAsync
我创建了一个简单的类来跟踪方法的调用方式:
using (var sw = new StreamWriter(messageWriter, Encoding.UTF8))
{
await sw.WriteAsync("Hi");
await sw.FlushAsync()
}
这个测试:
public class MSWrite : MemoryStream
{
public override bool CanWrite { get { return true; } }
public override void Write(byte[] buffer, int offset, int count)
{
Console.WriteLine("Write");
}
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
Console.WriteLine("WriteAsync");
return Task.Run(() => { });
}
}
收率:
Console.WriteLine("Simple");
using(var ms = new MSWrite())
using (StreamWriter sw = new StreamWriter(ms, Encoding.UTF8))
{
await sw.WriteAsync("Hi");
}
Console.WriteLine();
Console.WriteLine("AutoFlush");
using (var ms = new MSWrite())
using (StreamWriter sw = new StreamWriter(ms, Encoding.UTF8))
{
sw.AutoFlush = true;
await sw.WriteAsync("Hi");
}
Console.WriteLine();
Console.WriteLine("Flush async");
using (var ms = new MSWrite())
using (StreamWriter sw = new StreamWriter(ms, Encoding.UTF8))
{
await sw.WriteAsync("Hi");
await sw.FlushAsync();
}
第一次写入是UTF8 BOM,第二次是实际数据。
答案 1 :(得分:2)
不,StreamWriter.WriteAsync
实际上会调用Stream.WriteAsync
(假设您使用的是.NET 4.5)。如果您没有看到,请发布堆栈跟踪。
请注意,默认情况下,Stream
基类将在线程池线程上实现WriteAsync
Write
。您需要在自定义流中覆盖WriteAsync
才能更改此行为。