使用StreamWriter Async时,我收到错误“流当前正在流上的上一个操作使用”

问题描述 投票:-1回答:1

我有一组任务,可以将我尝试协调的字符串转换为流。这一切看起来都不错,但实际上我得到了一个

该流当前正在流上的先前操作中使用

Task.WhenAll电话之后。

例:

    private readonly List<Task<string>> _objectData = new List<Task<string>>();
    private readonly SemaphoreSlim _writerSemaphore = new SemaphoreSlim(1, 1);

    private async Task SafelyWrite(StreamWriter streamWriter, string field)
    {
        await _writerSemaphore.WaitAsync();

        if (field.IsNullOrWhiteSpace())
        {
            return;
        }

        streamWriter.Write(field);

        await streamWriter.FlushAsync();

        _writerSemaphore.Release();
    }

    public override async Task Build(StreamWriter streamWriter)
    {
        streamWriter.Write('{');

        await Task.WhenAll(
            _objectData.Select(async str => SafelyWrite(streamWriter, await str)));

        // await Task.Delay(10);

        // If I don't wait for a few milliseconds the app
        // will throw an error on this line that the stream
        // is currently being written to?
        streamWriter.Write('}');

        await streamWriter
            .FlushAsync();
    }

如果我查看流的内容,有或没有延迟,它都是有效的。一切都已经完成,只是StreamWriter认为它没有?如果我等待几毫秒,StreamWriter认为一切都已完成,我可以写封闭块。

Task.WhenAllSemaphoreSlim之间有什么东西我错过了吗?

(对不起代码量,它似乎是最小的失败,但有用的完整,例子)

c# async-await semaphore streamwriter
1个回答
-1
投票

无论应用这种方法将数据写入流的理由,这里的问题都存在于您只是“发射并忘记”异步任务的地方。特别是如果你仔细看看_objectData.Select(async str => SafelyWrite(streamWriter, await str)),你会看到这里是枚举器,里面启动等待str任务,但实际上并没有等待更高级别的这些进程的完成。而不是

await Task.WhenAll(_objectData.Select(async str => SafelyWrite(streamWriter, await str)));

应该有

await Task.WhenAll((await Task.WhenAll(_objectData)).Select(str => SafelyWrite(streamWriter, str)));

只是为了增加可读性并且为了避免对第二个选项的误解,这里是等效的:

var results = await Task.WhenAll(_objectData);
var writeTasks = results.Select(str => SafelyWrite(streamWriter, str));
await Task.WhenAll(writeTasks);
© www.soinside.com 2019 - 2024. All rights reserved.