0

I am creating a TagHelper for a RazorPage. The TagHelper class's only requirement is that the process method get overridden.

Here is the signature (and thank you for the solution Stephen let's just assume that ProcessAsync doesn't exist so we can still answer the question).

public override void Process(TagHelperContext context, TagHelperOutput output)

The body is very simple

if(_roleService.CanRegisterAsync().Result)
{
    output.SuppressOutput();
}

I hear that deadlocks can be caused by calling .Result on async methods so I don't want to call it as written above because it seems like I could run into some trouble.

So, I change the virtual override by adding async to

public override async void Process(TagHelperContext context, TagHelperOutput output)

and the body to

if(await _roleService.CanRegisterAsync())
{
    output.SuppressOutput();
}

This compiles fine but the output.SupressOutput() doesn't to seem to have any effect anymore so I am forced to go back to the original code which seems like a bad idea.

Is there any better way to deal with this situation so I don't potentially run into deadlocks as many people talk about in other async posts?

jwize
  • 4,230
  • 1
  • 33
  • 51
  • https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.run?view=netframework-4.8 – Zakk Diaz May 24 '19 at 18:12
  • 1
    Stephen's is the right answer, but for reference, here's [How to call asynchronous method from synchronous method](https://stackoverflow.com/questions/9343594/how-to-call-asynchronous-method-from-synchronous-method-in-c) – John Wu May 24 '19 at 18:26
  • Yeah thanks, I will read through it. Why not given him a vote since it is correct. – jwize May 24 '19 at 18:28
  • I am not sure why question is down voted. The answer to the problem is solved by Stephen but the answer to the question is probably closer to John Wu's comment and still doesn't have a proper answer. – jwize Jun 02 '19 at 00:07

2 Answers2

2

You need to create an asynchronous tag helper; in other words, override ProcessAsync instead of Process. That way you can use await:

public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
  if(await _roleService.CanRegisterAsync())
  {
    output.SuppressOutput();
  }
  ...
}
Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • 1
    Yes, this is a great answer. I tried and it works but what to do when this isn't an async override available? I can think of one instance where the same problem has arisen while I was writing some IdentityServer4 code. – jwize May 24 '19 at 18:24
0

Apparently what you are after is the following:

if(_roleService.CanRegisterAsync().WaitAndUnwrapException())
{
    output.SuppressOutput();
}

Remark: The name of the method strongly suggests using a try/catch to handle possible exceptions

Samuel Vidal
  • 883
  • 5
  • 16