locked
How to access data returned from async calls RRS feed

  • Question

  • Will calls to async functions return data in a passed buffer even though the buffer isn't passed by reference (which isn't allowed)?

    Microsoft's example appears to do so
      :

    using (FileStream SourceStream = File.Open(filename, FileMode.Open))
    {
        result = new byte[SourceStream.Length];
        await SourceStream.ReadAsync(result, 0, (int)SourceStream.Length);
    }
    
    UserInput.Text = uniencoding.GetString(result);



    I'm finding the same thing in my code.

    I have a main module that  asynchronously calls a function in another module.  That function performs an asynchronous read on a Filestream.

    This is the function call in the main module:

    // fileStreamDeviceData is a Filestream
    // inputReportBuffer is a byte array to hold the data being read.
    var isuccess = await MyHid.GetInputReportViaInterruptTransfer
      (fileStreamDeviceData, inputReportBuffer);

    In the MyHid module, the GetInputReportViaInterruptTransfer function contains this code:

    // OnTimeout is another function in the module.
    
    Action onReadTimeoutAction = OnTimeout;
    
    var cts = new CancellationTokenSource();
    
    cts.CancelAfter(5000); 
    
    cts.Token.Register(() => onReadTimeoutAction()); 
    
    Task t = fileStreamDeviceData.ReadAsync(inputReportBuffer, 0, inputReportBuffer.Length, cts.Token);
    await t;



    When the read operation completes, t.IsCompleted is true and inputReportBuffer in the main module contains the data read.

    I don't see any documentation that explicitly states that the passed buffer can return data for these asynchronous calls. Can I rely on this behavior?

    Return value

    The Filestream.ReadAsync documentation says that the value of the TResult parameter contains the total number of bytes read into the buffer. My call above returns a Task with properties such as IsCompleted, etc. Intellisense shows that one of the properties is Result (not TResult), with a value of 3, but this:

    if (t.Result > 0)

    gives the error "System.Threading.Tasks.Task doesn't contain a definition for Result".

    How do I access the Result value?











    Monday, February 4, 2013 5:39 PM

Answers

  • First, you might want to format your question properly, it's really hard to read right now.

    Async methods can modify the passed in array, because array is a reference type, there is no need for ref here.

    Your code doesn't work, because you're implicitly casting Task<int> into Task. If you change your code to use Task<int> (or var), you will be able to access the Result property (yeah, the documentation of ReadAsync() is confusing). But the result of the Task<int> is also returned from the await operator. That means a better way would be:

    int count = await fileStreamDeviceData.ReadAsync(inputReportBuffer, 0, inputReportBuffer.Length, cts.Token);
    You shouldn't use Result in async code, because it blocks if the value is not yet ready. But you can always use the result of await instead.
    Monday, February 4, 2013 6:43 PM

All replies

  • First, you might want to format your question properly, it's really hard to read right now.

    Async methods can modify the passed in array, because array is a reference type, there is no need for ref here.

    Your code doesn't work, because you're implicitly casting Task<int> into Task. If you change your code to use Task<int> (or var), you will be able to access the Result property (yeah, the documentation of ReadAsync() is confusing). But the result of the Task<int> is also returned from the await operator. That means a better way would be:

    int count = await fileStreamDeviceData.ReadAsync(inputReportBuffer, 0, inputReportBuffer.Length, cts.Token);
    You shouldn't use Result in async code, because it blocks if the value is not yet ready. But you can always use the result of await instead.
    Monday, February 4, 2013 6:43 PM
  • Thank you.
    Monday, February 4, 2013 7:07 PM