Alex Kay
Alex Kay

Reputation: 289

C# Delegate and async

I have the following code:

private void LoadImage() {
   (...some irrelevant code...)
   LoadIm = (obj) => {
      var img = new Image();
      img.Source = new StreamImageSource() {
         Stream = (token) => getstream(token)
      };
   };
   (...some other irrelevant code...)
}

private async Task<Stream> getstream(object token) {
   return new MemoryStream(someBytes);
}

It works fine but produces an annoying compile time warning: "This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread."

What's the proper way to handle it? The StreamImageSource expects an async, so I can't make getstream() synchronous.

Thanks in advance.

Upvotes: 0

Views: 746

Answers (2)

Jan Jurn&#237;ček
Jan Jurn&#237;ček

Reputation: 136

Your getstream method is synchronous and returns an instance of type MemoryStream.

If it should return a Task, wrap the result to Task with the static method Task.FromResult:

private async Task<Stream> getstream(byte[] someBytes) {
   return Task.FromResult<Stream>(new MemoryStream(someBytes));
}

The Stream property of the Xamarin.Forms.StreamImageSource class is of type Func<CancellationToken,Task>.So set it to the delegate like this (I assume that you have previously declared and filled someBytes objects - edit - completed code):

using System;
using System.IO;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace Demo
{
    public class Foo
    {
        public Action<object> LoadIm { get; private set; }

        // ....

        // Declare and fill the someBytes array
        byte[] someBytes = new byte[100];

        private void LoadImage()
        {
            LoadIm = (obj) => {
                var img = new Image();
                img.Source = new StreamImageSource()
                {
                    Stream = (token) => getstream(someBytes)
                };
            };
        }

        private Task<Stream> getstream(byte[] someBytes)
        {
            return Task.FromResult<Stream>(new MemoryStream(someBytes));
        }
    }
}

Upvotes: 0

ProgrammingLlama
ProgrammingLlama

Reputation: 38860

You'll want to remove async from your method and return Task.FromResult since you're not actually doing any async work:

private Task<Stream> getstream(object token) {
   return Task.FromResult<Stream>(new MemoryStream(someBytes));
}

Next you need to call it correctly so that everything works. You can do one of two things:

  1. Change the signature of your method to match the delegate and assign it directly:
private Task<Stream> getstream(object token)

becomes

private Task<Stream> getstream(CancellationToken token)

with the following assignment

img.Source = new StreamImageSource() {
    Stream = getstream
};
  1. Add async and await to your current code:
img.Source = new StreamImageSource() {
    Stream = async (token) => await getstream(token)
};

Upvotes: 4

Related Questions