I have a function in c#, call it
public async Task<byte[]> PrintLetter(int Id)
{
some code here
return byte[2125];
}
I was calling it like this: (not sure what the point of the _ is)
_ = Task.Run(async () => await PrintLetter(cid));
And it was running the print job and working fine.
But now I want to assign this PrintLetter()
to a variable so I can pass along this byte[]
and not just print to printer.
So I wanted to do this:
var files = await PrintLetter(cid);
return Ok(File(files, "application/pdf", "Letter.pdf"));
But I'm nervous to blindly remove the Task.Run
here.
Any advice
CodePudding user response:
You could just await
the result of the existing Task.Run
invocation:
byte[] bytes = await Task.Run(async () => await PrintLetter(cid));
In this case the async/await can be safely elided from the lambda. The behavior of the code below is identical:
byte[] bytes = await Task.Run(() => PrintLetter(cid));
Removing the Task.Run
is not a no-op though. It might be OK, or it might not. You can check out this question for guidance: await Task.Run vs await
CodePudding user response:
_ = Task.Run(async () => await PrintLetter(cid));
So, what this is actually doing is a form of fire-and-forget:
- The
Task.Run
ensures thatPrintLetter
runs outside of the ASP.NET request context. (I'm assuming this is ASP.NET pre-Core). - The
_ =
discards the task.
So this will execute PrintLetter
in a separate thread and not wait for it to complete before returning to the client.
The problem is that fire-and-forget is dangerous. This was never a good solution to begin with. Fortunately, the new requirements (passing back the byte array) means that the fire-and-forget should be removed anyway. This just leaves this:
var files = await PrintLetter(cid);
return Ok(File(files, "application/pdf", "Letter.pdf"));