I would like to implement an instance of IRandomAccessStream
in C# (it will be returning data generated in realtime). The stream does not actually need to be writable or seekable, but I want to return my own data in the ReadAsync
method (which is actually part of IInputStream
).
public IAsyncOperationWithProgress<IBuffer, uint> ReadAsync(IBuffer buffer, uint count, InputStreamOptions options)
{
throw new NotImplementedException("To be done");
}
My two main questions are:
IAsyncOperationWithProgress
? Is there anything built into the framework to help with this?IBuffer
only has Length
and Capacity
properties (the concrete Buffer class doesn't offer any more either).How to Convert byte Array to IRandomAccessStream
I've found this blog article, hopefully this realization of IRandomAccessStream
can be a starting point for you.
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);
}
}
Use AsyncInfo.Run(Func<CancellationToken, IProgress<uint>, Task<IBuffer>>)
method to create IAsyncOperationWithProgress instance from a delegate.
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;
}
Usually you do not need to access the buffer data directly. But in case you need to do this in c# you can use System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBufferExtensions class to copy data to/from a buffer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With