【问题标题】:How can I implement IRandomAccessStream in C#?如何在 C# 中实现 IRandomAccessStream?
【发布时间】:2012-12-05 12:33:34
【问题描述】:

我想在 C# 中实现IRandomAccessStream 的实例(它将返回实时生成的数据)。该流实际上不需要是可写或可搜索的,但我想在ReadAsync 方法中返回我自己的数据(实际上是IInputStream 的一部分)。

public IAsyncOperationWithProgress<IBuffer, uint> ReadAsync(IBuffer buffer, uint count, InputStreamOptions options)
{
    throw new NotImplementedException("To be done");
}

我的两个主要问题是:

  1. 如何返回实现IAsyncOperationWithProgress 的东西?框架中是否有任何东西可以帮助解决这个问题?
  2. 如何将数据写入缓冲区? IBuffer 只有 LengthCapacity 属性(具体的 Buffer 类也不再提供)。

【问题讨论】:

标签: c# streaming windows-runtime


【解决方案1】:

How to Convert byte Array to IRandomAccessStream

我找到了这篇博客文章,希望IRandomAccessStream 的实现可以成为您的起点。

class MemoryRandomAccessStream : IRandomAccessStream
{
    private Stream m_InternalStream;

    public MemoryRandomAccessStream(Stream stream)
    {
        this.m_InternalStream = stream;
    }

    public MemoryRandomAccessStream(byte[] bytes)
    {
        this.m_InternalStream = new MemoryStream(bytes);
    }

    public IInputStream GetInputStreamAt(ulong position)
    {
        this.m_InternalStream.Seek((long)position, SeekOrigin.Begin);

        return this.m_InternalStream.AsInputStream();
    }

    public IOutputStream GetOutputStreamAt(ulong position)
    {
        this.m_InternalStream.Seek((long)position, SeekOrigin.Begin);

        return this.m_InternalStream.AsOutputStream();
    }

    public ulong Size
    {
        get { return (ulong)this.m_InternalStream.Length; }
        set { this.m_InternalStream.SetLength((long)value); }
    }

    public bool CanRead
    {
        get { return true; }
    }

    public bool CanWrite
    {
        get { return true; }
    }

    public IRandomAccessStream CloneStream()
    {
        throw new NotSupportedException();
    }

    public ulong Position
    {
        get { return (ulong)this.m_InternalStream.Position; }
    }

    public void Seek(ulong position)
    {
        this.m_InternalStream.Seek((long)position, 0);
    }

    public void Dispose()
    {
        this.m_InternalStream.Dispose();
    }

    public Windows.Foundation.IAsyncOperationWithProgress<IBuffer, uint> ReadAsync(IBuffer buffer, uint count, InputStreamOptions options)
    {
        var inputStream = this.GetInputStreamAt(0);
        return inputStream.ReadAsync(buffer, count, options);
    }

    public Windows.Foundation.IAsyncOperation<bool> FlushAsync()
    {
        var outputStream = this.GetOutputStreamAt(0);
        return outputStream.FlushAsync();
    }

    public Windows.Foundation.IAsyncOperationWithProgress<uint, uint> WriteAsync(IBuffer buffer)
    {
        var outputStream = this.GetOutputStreamAt(0);
        return outputStream.WriteAsync(buffer);
     }
}

【讨论】:

    【解决方案2】:
    1. 使用AsyncInfo.Run(Func&lt;CancellationToken, IProgress&lt;uint&gt;, Task&lt;IBuffer&gt;&gt;) 方法从委托创建 IAsyncOperationWithProgress 实例。

      public IAsyncOperationWithProgress<IBuffer, uint> ReadAsync(IBuffer buffer, uint count, InputStreamOptions options)
      {    
          if (buffer == null) throw new ArgumentNullException("buffer");
      
          Func<CancellationToken, IProgress<uint>, Task<IBuffer>> taskProvider =
          (token, progress) => ReadBytesAsync(buffer, count, token, progress, options);
      
          return AsyncInfo.Run(taskProvider);
      }
      
      private async Task<IBuffer> ReadBytesAsync(IBuffer buffer, uint count, CancellationToken token, IProgress<uint> progress, InputStreamOptions options)
      {
      ... Fill the buffer here. Report the progress.
          return buffer;
      }
      
    2. 通常您不需要直接访问缓冲区数据。但如果您需要在 c# 中执行此操作,您可以使用 System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBufferExtensions 类将数据复制到缓冲区/从缓冲区复制数据。

    【讨论】:

    • 你能解释一下吗?
    • 谢谢,看来这回答了我问题的第一部分。仍然不知道我是如何填充 IBuffer 的
    • 使用 WindowsRuntimeBufferExtensions 扩展方法。
    猜你喜欢
    • 1970-01-01
    • 2012-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-18
    • 2010-09-28
    • 2016-04-13
    • 2014-10-29
    相关资源
    最近更新 更多