ITPub博客

首页 > 应用开发 > > C# 8.0 抢先看-- Async Stream

C# 8.0 抢先看-- Async Stream

作者:helei1000 时间:2019-09-16 17:00:58 0 删除 编辑

如果一个方法要回传IAsyncEnumerable ,而方法内部使用yield return 该怎么写呢?

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


internal class AsyncEnumerator : IAsyncEnumerator<string>

{

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<bool> 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<string> 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();

}

}

    }

程式码没有错,但编译过不了,观察一下错误讯息:

错误CS0656:缺少编译器所需成员'System.Threading.Tasks.ManualResetValueTaskSourceLogic`1.GetResult'

错误CS0656:缺少编译器所需成员'System.Threading.Tasks.ManualResetValueTaskSourceLogic`1.GetStatus'

错误CS0656:缺少编译器所需的成员'系统。 Threading.Tasks.ManualResetValueTaskSourceLogic`1.get_Version' 

错误CS0656:缺少编译器所需成员'System.Threading.Tasks.ManualResetValueTaskSourceLogic`1.OnCompleted' 

错误CS0656:缺少编译器所需成员'System.Threading.Tasks.ManualResetValueTaskSourceLogic`1.Reset' 

错误CS0656:缺少编译器所需的成员'System.Threading.Tasks.ManualResetValueTaskSourceLogic`1.SetException'

错误CS0656:缺少编译器所需的成员'System.Threading.Tasks.ManualResetValueTaskLogic.cn 

.SetResult ' 错误CS0656:缺少编译器所需的成员'System.Runtime.CompilerServices.IStrongBox`1.get_Value' 

错误CS0656:缺少编译器所需的成员

很明显,编译器需要两个型别(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 @benaadamssaid 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.』,简单说就是编译器和框架目前的更新进度不一致,导致少了点什么。既然如此,我们就遵照本草纲目的指示,补上这两个型别,请注意,这两个型别的命名空间必须正确:


using System;

using System.Runtime.CompilerServices;

using System.Threading.Tasks.Sources;

namespace System.Threading.Tasks{

internal struct ManualResetValueTaskSourceLogic<TResult>

{

private ManualResetValueTaskSourceCore<TResult> _core;

public ManualResetValueTaskSourceLogic(IStrongBox<ManualResetValueTaskSourceLogic<TResult>> 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<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) => _core.OnCompleted(continuation, state, token, flags);

public void Reset() => _core.Reset();

public void SetResult(TResult result) => _core.SetResult(result);

public void SetException(Exception error) => _core.SetException(error);

}

}

namespace System.Runtime.CompilerServices

{

internal interface IStrongBox<T> { ref T Value { get; } }

}

补上去后就大功告成,可以快乐地非同步yielld return。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/2613/viewspace-3141632/ ,如需转载,请注明出处,否则将追究法律责任。

下一篇: mysql 模糊查询
请登录后发表评论 登录
全部评论

注册时间:2019-08-16

  • 博文量
    94
  • 访问量
    678