Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I handle an interface method that may or may not be async?

I am attempting to create a serialization interface (similar to Cocoa's NSCoding protocol) so that I can get a quick binary representation of a class to send across a network or store in a database. However, some cases (especially involving image encoding) have many async-only methods that require awaiting. However, if the bytes do not get written in order then of course the whole representation is corrupted. I must make sure that the current object is finished serializing before I continue to the next object. Here is the main loop of what I am doing.

 public async static Task<byte[]> Serialize(this IList<ISerializable> list) {
        using (Archiver archiver = new Archiver()) {
            archiver.Write(list.Count);
            foreach (ISerializable value in list) {
                await archiver.Write(value);
            }
            return archiver.Result;
        }
    }

Archiver just uses MemoryStream and BitmapWriter under the hood to write either values that BinaryWriter can accept directly, or ISerializable objects, and then spits out the result as a byte array. ISerializable is just an interface with two methods (Serialize and Deserialize). They both return Task so that they can be awaited. The problem is when I have a serialization method that doesn't have any async components. I can do one of two things:

A) I can tack on async to that class's serialization methods anyway and put up with the compiler warning saying that it will execute synchronously (I don't like to have compiler warnings).

B) Manually return an empty task at the end of the method (return Task.Run(() => {});). However, this looks and smells really weird.

Both A and B seem to execute without a problem, but are there any problems with this approach that I may have missed? I am not aware of a binary serializer in Windows Runtime (I included the tag just to dispel any confusion). Perhaps there is an option C that I can consider? Actually I didn't want to make the serialization methods async, but for some reason task.Wait() was not waiting, and I was getting a null reference exception from trying to use an object created with CreateAsync before it was ready.

EDIT I thought of an option C. I could just wrap the entire method in an await Task.Run(...) call. Would this be normal?

like image 369
borrrden Avatar asked Apr 16 '13 09:04

borrrden


1 Answers

I think the best solution here, assuming you want to execute the method synchronously is to write it normally, except you will return a completed Task at the end of the method.

To get a completed Task with some specific value, you can use Task.FromResult().

If you want a Task with no value (i.e. actually just Task, not Task<TResult>), you can use for example Task.FromResult(true) (which is a Task<bool>) and implicitly cast it to Task.

like image 139
svick Avatar answered Nov 15 '22 10:11

svick