0

I just want a sanity check on this, because I have little experience writing asynchronous functions.

I am subclassing an abstract class and need to override a function with the following signature:

public abstract Task WriteResponseBodyAsync(OutputFormatterWriteContext context);

The function must return task, and my override does not use any asynchronous functions, so to return Task I use Task.Run. Is this the correct usage?

public class FhirJsonFormatter : TextOutputFormatter
{    
    public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
    {
        Hl7.Fhir.Serialization.FhirJsonSerializer ser = new Hl7.Fhir.Serialization.FhirJsonSerializer();

        using (System.IO.StreamWriter sw = new System.IO.StreamWriter(context.HttpContext.Response.Body))
        {
            using (Newtonsoft.Json.JsonWriter jw= new Newtonsoft.Json.JsonTextWriter(sw))
            {
                return Task.Run(() => { ser.Serialize((Hl7.Fhir.Model.Base)context.Object, jw); });
            }
        }
    }
}
8
  • 2
    Use Task.FromResult. That's the best I can do rn :) Commented Jan 22, 2020 at 16:58
  • Or Task.CompletedTask if you have no return value besides Task Commented Jan 22, 2020 at 16:58
  • 3
    The main issue here is that the objects may be disposed before the task gets a chance to run. Commented Jan 22, 2020 at 17:02
  • It's usually a bad idea to try to make things async by wrapping them in Task.Run; this has overhead that may be detrimental. The caller may actually not want the task to run in a new thread. Make your code not break if the caller wants to call it inside a new thread, but let the caller make that decision. Commented Jan 22, 2020 at 17:14
  • 1
    Is FhirJsonSerializer code that you control? If so maybe think about adding async methods to it. It's best to do async code all the way from the top to the bottom rather than wrapping in Task.Run or just throwing out a Task.CompletedTask, if possible. Commented Jan 22, 2020 at 17:17

1 Answer 1

1

Task.Run will run the code on another thread, which is probably not what you want.

Why not just return Task.CompletedTask:

public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
{
    Hl7.Fhir.Serialization.FhirJsonSerializer ser = new Hl7.Fhir.Serialization.FhirJsonSerializer();

    using (System.IO.StreamWriter sw = new System.IO.StreamWriter(context.HttpContext.Response.Body))
    {
        using (Newtonsoft.Json.JsonWriter jw= new Newtonsoft.Json.JsonTextWriter(sw))
        {
            ser.Serialize((Hl7.Fhir.Model.Base)context.Object, jw);
        }
    }
    return Task.CompletedTask;
}

Also with your example, the method may return before ser.Serialize has finished, causing jw, sw and maybe even context to be disposed.

Sign up to request clarification or add additional context in comments.

3 Comments

Should I have wrapped all the code inside the method inside a Task.Run instead?
The downside here is that this blocks the current thread while the IO runs. That may or may not be a factor.
Task.Run will run the code on another thread not necessarily

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.