When consuming a component in another razor component, there is usually a need to call async methods triggered by an EventCallback property, onClick
for instance. Is there any particular way to call it to assure asynchronicity?
Let’s assume the following example:
@* CASE 1*@
<MyButton OnClick=DoSomething>Click Me</MyButton>
@* CASE 2*@
<MyButton OnClick=@(async () => await DoSomething())>Click Me</MyButton>
@code {
private async Task DoSomething(){ ... }
}
After compiling, is there any distinction between using a delegate or calling the function directly? Should we prefer one or the other?
This question doesn’t derive from an error or code running improperly but only from the fact that I get no feedback from Visual Studio and probably for a good reason but I would like to know if I’m writing improper code either way.
Choice Remark: Hard to pick a single answer for all provide valid points to the discussion, further reading is encouraged. It seems the confusion stems from a misunderstanding of the delegate’s role in the call stack, in that way I think that Shaun’s answer shows the most succinct and explicit example of that.
3
Answers
Lambda expressions are fully supported and in fact, in some cases they may be required. Consider you are doing a
@foreach(item in items)
to pass the item to the function you’d likely need to use a lambda expression:@(async () => await DoSomething(item))
Here is Microsoft documentation supporting lambas:
https://learn.microsoft.com/en-us/aspnet/core/blazor/components/event-handling?view=aspnetcore-7.0
In this specific case, the first is better.
This code block is wrapping a Task within a Task. It wasteful on resources: each Task is a state machine object.
However, what actually happens depends on
MyButton
.Here’s a demo version. I’ve added two button event handlers, with comments on how each executes.
More generally, it’s a matter of personal preference.
I like clean markup, so I code like this.
Others like succinct [inline] code.
The following snippet taken straight out of Microsoft docs:
As you can see lambda is not used (
@onclick="UpdateHeading"
) but still it is mentioned thatUpdateHeading
will be called asynchronously.Also when passing parameters, wrapping in async await is not required. The following will work correctly:
A lambda with async/await would be useful if instead of declaring
UpdateHeading
, you wanted to use anonymous method: