locked
IUriToStreamResolver.UriToStreamAsync - InvalidCastException in TaskToAsyncOperationWithProgress

    Question

  • Hi,

    I'm developping a book reader application and to display EPUb  I'm using a webview with a IUriToStreamResolver to get the resources (from disk or from server). My business code return Stream object (MemoryStream) and I'm using "AsRandomAccessStream" extension method to get a WinRt Stream (also tried with "AsInputStream").

    The issue is that I cannot return the result of these methods to the webview due to an InvalidCastException. The exception is not raised by the webview but by the "TaskToAsyncOperationWithProgressAdapter" in "OnCompleted" method.

    If I'm creating an "InMemoryRandomAccessStream" an copy the bytes in it's working. Copying mutiple times the same data (from server to stream/from stream to WinRt Stream/from WinRt stream to webview) is using too much memory and CPU for a mobile application.

    Is it a known issue? Did anyone have a fix for that?Thanks,

    Thanks,

    Max.

    Thursday, October 09, 2014 7:44 AM

All replies

  • It's difficult to say without seeing the project. Can you post it to OneDrive and share a link here?

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Friday, October 10, 2014 12:51 PM
    Moderator
  • Hi,

    I made a demo project with the same issue. It's available at https://onedrive.live.com/redir?resid=515FB7945D55A902!38419&authkey=!AAZ-8OeQgqUfHXA&ithint=file%2czip

    Thanks for your help.

    Max.

    Monday, October 13, 2014 7:33 AM
  • Does this code work for you?
    async private Task<IInputStream> GetContent(SectionViewModel viewModel)
    {
      Stream stream = await viewModel.GetContentAsync();
      IRandomAccessStream R = stream.AsRandomAccessStream();
      return R.GetInputStreamAt(0);
    }


    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Monday, October 13, 2014 2:38 PM
    Moderator
  • No it's not working. I have an "NotSupportedException"

    "Additional information: This IRandomAccessStream does not support the GetInputStreamAt method because it requires cloning and this stream does not support cloning."

    AsRandomAccessStream(): create a wrapper and don'tcopy the content of the MemoryStream. And this wrapper is not cloneable.


    The InvalidCastException is thrown by "System.StubHelpers.InterfaceMarshaler.ConvertToNative(Object objSrc, IntPtr itfMT, IntPtr classMT, Int32 flags)"
    • Edited by MxDeg Tuesday, October 14, 2014 9:46 AM
    Tuesday, October 14, 2014 6:20 AM
  • Hi,

    After multiple try I found the reason but cannot fix it.

    It seems that if the UriToStreamAsync method of IUriToStreamResolver doesn't return a WinRT implement of "IInputStream" ("InMemoryRandomAccessStream" or "FileRandomAccessStream") the webview (or the component that use the "IUriToStreamResolver") call the "ReadAsync" method. This method return a "IAsyncOperationWithProgress<IBuffer, uint>". But there is a bug when setting the "Completed" handler on this instance. The type needed by the "Completed" property is "AsyncOperationWithProgressCompleteHandler<IBuffer, uint>". BUT the type passed to this property is in fact a "AsyncOperationCompleteHandler<IInputStream>" which indeed is not correct and throw a "InvalidCastException". I tried to create my own implementation of "IAsyncOperationWithProgress" to handle this specific case but a "AccessViolationException" is thrown when called the "Complete" delegate.

    Please note that this issue doesn't appears with "InMemoryRandomAccessStream" or "FileRandomAccessStream". I assume these two classes follow a more optimized way.

    I really need to use a custom IRandomAccessStream to handle encryption of the data that I need to display.

    Thanks for the help.

    Max.

    Wednesday, February 04, 2015 12:23 PM