locked
Issue with StorageFile.GetFileAsync RRS feed

  • Question

  • can any body explain this, i can't work out what i am doing wrong.

    I am calling the following method from within in a for loop. eg

    for(String filename in files)

    {

            byte[] a = GetFileStream(filename).Result;

    }

    It works fine for the first file i pass in. On the second file it just freezes on this line:

    StorageFile file = await StorageFile.GetFileFromPathAsync(filename);

    It doesn't seem to be an issue with file locks as i have tried it with different combinations of files.

    The files are all in the same location and i have granted my app privileges to the necessary library.

            private static async Task<Byte[]>  GetFileStream(String filename)
            {
                try
                {
                    StorageFile file = await StorageFile.GetFileFromPathAsync(filename);
                    Stream documentFileStream = await file.OpenStreamForReadAsync();
                    Byte[] streamArray = new Byte[documentFileStream.Length];
                    await documentFileStream.ReadAsync(streamArray, 0, Convert.ToInt32(documentFileStream.Length));
                    return streamArray;
                }
                catch (Exception x)
                {
                    throw x;
                }
            }

    Monday, October 28, 2013 3:26 AM

Answers

  • I suspect you're deadlocking when you block waiting on Task.Result. If you use await instead you shouldn't have a problem. You should be able to see this in the debugger by examining the threads calling and implementing GetFileStream.

    Instead of:

    byte[] a = GetFileStream(filename).Result;
    do:
    byte[] a = await GetFileStream(filename);

    --Rob

    • Marked as answer by c.j.mcnaught Tuesday, October 29, 2013 10:04 PM
    Monday, October 28, 2013 4:38 AM
    Moderator

All replies

  • Hello c.j.mcnaught,

    why you use 

    StorageFile file = await StorageFile.GetFileFromPathAsync(filename);

    use this type

    StorageFile file = await LocalFolder.GetFileAsync(filename);

    may be it works.

    Monday, October 28, 2013 4:22 AM
  • well at this stage the files are not in local folder they could be in one of several locations.

    Monday, October 28, 2013 4:28 AM
  • I suspect you're deadlocking when you block waiting on Task.Result. If you use await instead you shouldn't have a problem. You should be able to see this in the debugger by examining the threads calling and implementing GetFileStream.

    Instead of:

    byte[] a = GetFileStream(filename).Result;
    do:
    byte[] a = await GetFileStream(filename);

    --Rob

    • Marked as answer by c.j.mcnaught Tuesday, October 29, 2013 10:04 PM
    Monday, October 28, 2013 4:38 AM
    Moderator
  • Hi Rob,

    I can get it to work by doing that but it will break another part of my application.

    I need the method that calls GetFileStream to run synchronosouly.

    Monday, October 28, 2013 4:46 AM
  • Hello c.j.mcnaught,

    try this code:

    StorageFile file = await StorageFile.GetFileFromPathAsync(filename);
    
    //get binary content of the file using WINRT api
    IBuffer buffer = await FileIO.ReadBufferAsync(file);
    byte[] bytes = buffer.ToArray();

    or if you want to use BinaryReader then

    StorageFile file = await StorageFile.GetFileFromPathAsync(filename);
    
    Stream stream = (await file.OpenReadAsync()).AsStreamForRead();
    BinaryReader reader = new BinaryReader(stream);

    Monday, October 28, 2013 5:59 AM
  • Hi Nipun,

    What namespace does IBuffer belong to?

    I including Windows.Storage.Streams

    and the compiler says that IBuffer.ToArray() does not exist?

    Tuesday, October 29, 2013 12:10 AM
  • Khant's "solution" is basically the same as yours. It will have the same deadlock if you block on getting the result.

    What is the context in which you are calling this? If you are calling it on the UI thread then you need to make everything asynchronous and have the dependent call use await. Blocking the UI thread always a bad idea.

    If you are calling it on a worker thread then you can make it asynchronous, but you'll either need to make it all asynchronous or deal with thread synchronization yourself so you don't end up with two threads waiting on each other like you do here.

    ToArray is an extension method, not part of IBuffer itself. The easiest way to find it is in the Object browser. See my video Visual Studio's Red Squigglies for an example of finding it in the System.Runtime.InteropServices.WindowsRuntime namespace.

    --Rob

    Tuesday, October 29, 2013 12:51 AM
    Moderator