C# 8.0 抢先看 -- Async Stream (2)

2021-02-04 18:14

阅读:613

标签:ati   str   mis   visual   微软   like   value   complete   yield   

在目前版本中异步迭代使用 yield return 的暂时解决方案说明。


本篇文章使用环境
开发环境 Visual Studio 2019 Preview 1 (16.0.0 Preview 1)
框架?????? .NET Core 3.0.0-preview-27122-01
编译器??? C# 8.0 beta

上一篇简单示范了在类中实践 Async Stream 的方式, 如果今天是一个方法要回传 IAsyncEnumerable ,而方法内部使用 yield return 该怎么写呢?

我们一样就拿 ReadLineAsync 来示范,首先建立一个类实践 IAsyncEnumerator ,当然这也包含了实践 IAsyncDisposable:

    internal class AsyncEnumerator : IAsyncEnumerator
    {
        private readonly StreamReader _reader;

        private bool _disposed;

        public string Current { get; private set; }

        public AsyncEnumerator(string path)
        {
            _reader = File.OpenText(path);
            _disposed = false;
        }
        async public ValueTask MoveNextAsync()
        {
            var result = await _reader.ReadLineAsync();
            Current = result;
            return result != null;
        }
        async public ValueTask DisposeAsync()
        {
            await Task.Run(() => Dispose());
        }

        private void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if (!this._disposed)
            {
                if (_reader != null)
                {
                    _reader.Dispose();
                }
                _disposed = true;
            }
        }
    }

接着建立另外一个类, 这个类很简单,只包含一个静态的方法 async static public IAsyncEnumerable ReadLineAsync(string path),实践内容如下:

        async static public IAsyncEnumerable ReadLineAsync(string path)
        {

            var enumerator = new AsyncEnumerator(path);
            try
            {
                while (await enumerator.MoveNextAsync())
                {
                    await Task.Delay(100);
                    yield return enumerator.Current;
                }
            }
            finally
            {
                await enumerator.DisposeAsync();
            }
        }
    }

程序没有错,但编译过不了,观察一下错误消息:

error CS0656: Missing compiler required member ‘System.Threading.Tasks.ManualResetValueTaskSourceLogic`1.GetResult‘
error CS0656: Missing compiler required member ‘System.Threading.Tasks.ManualResetValueTaskSourceLogic`1.GetStatus‘
error CS0656: Missing compiler required member ‘System.Threading.Tasks.ManualResetValueTaskSourceLogic`1.get_Version‘
error CS0656: Missing compiler required member ‘System.Threading.Tasks.ManualResetValueTaskSourceLogic`1.OnCompleted‘
error CS0656: Missing compiler required member ‘System.Threading.Tasks.ManualResetValueTaskSourceLogic`1.Reset‘
error CS0656: Missing compiler required member ‘System.Threading.Tasks.ManualResetValueTaskSourceLogic`1.SetException‘
error CS0656: Missing compiler required member ‘System.Threading.Tasks.ManualResetValueTaskSourceLogic`1.SetResult‘
error CS0656: Missing compiler required member ‘System.Runtime.CompilerServices.IStrongBox`1.get_Value‘
error CS0656: Missing compiler required member ‘System.Runtime.CompilerServices.IStrongBox`1.Value‘

很明显,编译器需要两个类型 (1)? System.Threading.Tasks.ManualResetValueTaskSourceLogic (2) System.Runtime.CompilerServices.IStrongBox 才能完成编译。感谢 open source 与 git hub,在微软的 dotnet/corclr 的项目中找到了这么一段讨论 ~~ ManualResetValueTaskSourceLogic`1 missing in System.Private.CoreLib #21379 ,有位 stephentoub (应该是微软员工而且是这个项目的成员) 提到‘It‘s not missing exactly, but like @benaadams said things are just out-of-sync between the compiler and library in Preview 1. The compiler is looking for the old design (ManualResetValueTaskSourceLogic and IStrongBox), while the libraries include the approved API surface area (ManualResetValueTaskSourceCore), and we didn‘t have time to get the compiler updated. You just need to include a bit of boilerplate in your app’,简单说就是编译器和框架目前的更新进度不一致,导致少了点什么。既然如此,我们就遵照本草纲目的指示,补上这两个类型,请注意,这两个类型的命名空间必须正确:

using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks.Sources;


namespace System.Threading.Tasks{
   
    internal struct ManualResetValueTaskSourceLogic
    {
        private ManualResetValueTaskSourceCore _core;
        public ManualResetValueTaskSourceLogic(IStrongBox> parent) : this() { }
        public short Version => _core.Version;
        public TResult GetResult(short token) => _core.GetResult(token);
        public ValueTaskSourceStatus GetStatus(short token) => _core.GetStatus(token);
        public void OnCompleted(Action

补上去后就大功告成,可以快乐地异步 yielld return。故事还没完,待续........


原文:大专栏  C# 8.0 抢先看 -- Async Stream (2)


C# 8.0 抢先看 -- Async Stream (2)

标签:ati   str   mis   visual   微软   like   value   complete   yield   

原文地址:https://www.cnblogs.com/petewell/p/11457971.html


评论


亲,登录后才可以留言!