문제

I'm having hard time trying to figure out how to properly handle exceptions within async functions. Having the following code:

static async Task NotifyPartyAsync(Uri uri, string paramName, string paramValue)
{
    string link = string.Format("{0}?{1}={2}", uri, paramName, HttpUtility.UrlEncode(paramValue));
    using (var client = new HttpClient())
        try {
            using (HttpResponseMessage response = await client.GetAsync(link, HttpCompletionOption.ResponseHeadersRead))
                logger.DebugFormat("HTTP {0} from {1}", (int)response.StatusCode, link);
        }
        catch (Exception ex)    {
            logger.Error(ex);
        }
}

static void NotifyParty(Uri uri, string paramName, string paramValue)
{
    string link = string.Format("{0}?{1}={2}", uri, paramName, HttpUtility.UrlEncode(paramValue));
    using (var client = new HttpClient())
        try {
            using (HttpResponseMessage response = client.GetAsync(link, HttpCompletionOption.ResponseHeadersRead).Result)
                logger.DebugFormat("HTTP {0} from {1}", (int)response.StatusCode, link);
        }
        catch (Exception ex)    {
            logger.Error(ex);
        }
}

How do I refactor it to not repeat 99% code common to both functions? I need to notify an uri both synchronously and asynchronously and I don't care about the result except I want it logged.

도움이 되었습니까?

해결책

Basically, with async/await you can follow the same pattern you do for synchronous programming. Don't handle exceptions inside every async method, unless absolutely required. Handle them on the topmost level, i.e., inside the outermost async or synchronous method. What's this method is depends on the execution environment.

E.g., it might be an async void event handler in case it's a UI app:

async Task DoWorkAsync()
{
    // don't handle exceptions here
}

async void Form_Load(object s, EventArgs args)
{
    try {
        await DoWorkAsync();
    }
    catch (Exception ex) 
    {
        // log
        logger.Error(ex);
        // report
        MessageBox.Show(ex.Message);
    }
}

Or, it may be the Main entry point of a console app:

static void Main(string[] args)
{
    try {
        DoWorkAsync().Wait();
    }
    catch (Exception ex) 
    {
        // log
        logger.Error(ex);
        throw; // re-throw to terminate
    }
}

You should understand though how exceptions get propagated for async methods. Check this for some more details.

Also, not all exceptions are the same and should be handled equally. Check Eric Lippert's "Vexing exceptions".

다른 팁

You should look at this question: Good pattern for exception handling when using async calls. It might be what you're looking for.

static void NotifyParty(Uri uri, string paramName, string paramValue)
{
  await NotifyPartyAsync(uri, paramName, paramValue);
}

OR

static void NotifyParty(Uri uri, string paramName, string paramValue)
{
  NotifyPartyAsync(uri, paramName, paramValue).Wait();
}

let me know if you're working with .net 4.5 or 4.0. there may be some nuances based on that.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top