0

I have created a logging library and the log method returns an error number (PK), upon making an entry into DB, which I notify to users as part of the error message on their UI. They further use that key as a reference when they talk to support team.

And I have an async method for doing the same, as below:

public class Logger
{
  public async Task<string> LogAsync(Exception ex)
  {
    return await DoLogAsync(ex);
  } 

  // some private method, with multiple optional parameters
  private Task<string> DoLogAsync(Exception ex)
  {
    return Task.Run(() => Log(ex));
  }
}

Note: I admit, this async version is nothing but simply wraps the synchronous method, Log(), in Task.Run. I am not sure, what else should be done!!

Now, i’m planning to use the above Log() method, in all my APIs, like below:

public Result<MyObject> Get()
{
  var result = new Result<MyObject>();

  try
  {
    throw new DivideByZeroException();
  }
  catch (DivideByZeroException ex)
  {
    string errorId = await _logger.LogAsync(ex);
    response.AddErrorMessage("Please Contact Admin with this error #"+errorId);
  }

  return result;
}

In order to make above work, I need to make the API method async, since i am awaiting the logger call.

  1. How should I avoid changing my API call async, just for the sake of Logger? What are other possibilities of making this work?
  2. Do you think, LogAsync() would really be beneficial? My UI thread will be waiting for the error number to be returned anyways, so why not just call the sync method?
  3. There are few Log() methods, which doesn’t need an error number, in return, kind of log-and-forget. Do you think, async versions, will be helpful in such scenarios, because UI won’t expect anything back?

Answer: For the question 1, this works: Waiting for async/await inside a task

Also for 2, and 3, having ADO.Net implementations make much sense, rather than Task.Run

Community
  • 1
  • 1
Skip
  • 33
  • 6
  • Is this a web app? – JohanP Feb 05 '17 at 22:07
  • that is c#... please mid the tags :) – ymz Feb 05 '17 at 22:09
  • 1
    C# is a language. You can use C# for ASP.Net apps as well as Web APIs. – JohanP Feb 05 '17 at 22:11
  • Yes! WebAPI for now but we have many other consumers – Skip Feb 05 '17 at 22:12
  • So.. in that case you know that c# is running over your **server**... anyhow.. please check this post: http://stackoverflow.com/questions/24777253/waiting-for-async-await-inside-a-task – ymz Feb 05 '17 at 22:12
  • What does `Log` method do? Please be specific, maybe even post the code. – CodingYoshi Feb 05 '17 at 22:20
  • @ymz, that answers my question 1. thanks – Skip Feb 05 '17 at 22:31
  • @CodingYoshi, Log() method actually creates a log entry into SQL database and returns the primary key, just inserted. – Skip Feb 05 '17 at 22:31
  • @Skip... thanks for your kind feedback...please edit your post and share the link and solution in **bold** - that may be useful to others (who don't read the entire comments block - shame on you lol) – ymz Feb 05 '17 at 22:36
  • In a web api, you should try and doing everything on one thread. Async does not mean you need to start a new thread. Make your action async and call the asynchronous version of the log method and await it without starting a task and delegating the work to a thread pool thread. – CodingYoshi Feb 05 '17 at 22:50
  • @CodingYoshi, thanks.. i'll keep that in mind – Skip Feb 06 '17 at 04:11
  • You may want to read [Should I expose asynchronous wrappers for synchronous methods?](https://blogs.msdn.microsoft.com/pfxteam/2012/03/24/should-i-expose-asynchronous-wrappers-for-synchronous-methods/) by Stephen Toub. – Damien_The_Unbeliever Feb 07 '17 at 14:54

2 Answers2

0

If you're using Web API I would not go for an async Log method if the method is not truly async. Have a look at this answer from Stephen Cleary.

Community
  • 1
  • 1
JohanP
  • 5,252
  • 2
  • 24
  • 34
  • wow.. so i do not need to expose an async method; rather i would utilize ADO.Net async methods inside.. thanks – Skip Feb 05 '17 at 22:32
  • 1
    If you're using ADO.Net in your app for DB access, then yes, you should use its `async` methods. This means that your `Log` method will still be `async` tho, but you don't have to wrap it in a `Task.Run` – JohanP Feb 05 '17 at 22:34
  • thanks for further advise. Yes; i am able to successfully utilize them – Skip Feb 06 '17 at 03:59
  • No. For this answer to be more accurate it should say: do not use `Task.Run` in a web or a web service scenario even if the method is truly async. Especially when it is not truly async. – CodingYoshi Feb 06 '17 at 04:23
  • @johanp read my comment again. According to your answer, without reading the link, if log method is truly async then it's ok to use task.run – CodingYoshi Feb 06 '17 at 12:13
  • Your comment is wrong and that is NOT what it says. Why would I tell op to not use Task.Run but then say it is ok to use it if the method is truly async. Are you kidding me? – JohanP Feb 06 '17 at 19:21
0

If you start using async-await approach in your code - be aware that async will spread over whole pipeline of your application.

So

How should I avoid changing my API call async, just for the sake of Logger? What are other possibilities of making this work?

Answer: Do not use async

Do you think, LogAsync() would really be beneficial? My UI thread will be waiting for the error number to be returned anyways, so why not just call the sync method?

Answer: Benefit is that during waiting, UI will be "responsive" - user for example will be able to move window of the application on another screen or minimize it.

There are few Log() methods, which doesn’t need an error number, in return, kind of log-and-forget. Do you think, async versions, will be helpful in such scenarios, because UI won’t expect anything back?

Answer: same as previous answer

Servy
  • 202,030
  • 26
  • 332
  • 449
Fabio
  • 31,528
  • 4
  • 33
  • 72
  • Thanks; So, Instead of making the API async, I would like to use as below, as someone suggested in another post: `var t = Task.Run( async () => { await lIB.LogAsync(); });` Any side affects to that approach, you think? – Skip Feb 07 '17 at 15:29
  • Side effects: you wasting resources by reserving/creating another Thread only for doing nothing. In IO operation (which database query is) the thread will send request and wait for response. – Fabio Feb 07 '17 at 16:34
  • thanks; It seems, i'll be better off w/o async in this scenario – Skip Feb 07 '17 at 16:50