/// <summary> /// <see cref="IDevice.ReadAsync(int, ulong, IntPtr, uint, IOCompletionCallback, IAsyncResult)">Inherited</see> /// </summary> public override unsafe void ReadAsync(int segmentId, ulong sourceAddress, IntPtr destinationAddress, uint readLength, IOCompletionCallback callback, IAsyncResult asyncResult) { // It is up to the allocator to make sure no reads are issued to segments before they are written if (!blobs.TryGetValue(segmentId, out BlobEntry blobEntry)) { throw new InvalidOperationException("Attempting to read non-existent segments"); } // Even though Azure Page Blob does not make use of Overlapped, we populate one to conform to the callback API Overlapped ov = new Overlapped(0, 0, IntPtr.Zero, asyncResult); NativeOverlapped *ovNative = ov.UnsafePack(callback, IntPtr.Zero); UnmanagedMemoryStream stream = new UnmanagedMemoryStream((byte *)destinationAddress, readLength, readLength, FileAccess.Write); CloudPageBlob pageBlob = blobEntry.GetPageBlob(); pageBlob.BeginDownloadRangeToStream(stream, (Int64)sourceAddress, readLength, ar => { try { pageBlob.EndDownloadRangeToStream(ar); } // I don't think I can be more specific in catch here because no documentation on exception behavior is provided catch (Exception e) { Trace.TraceError(e.Message); // Is there any documentation on the meaning of error codes here? The handler suggests that any non-zero value is an error // but does not distinguish between them. callback(2, readLength, ovNative); } callback(0, readLength, ovNative); }, asyncResult); }