【问题标题】:How to wait for async method to finish when calling a external service in .net core?在.net核心中调用外部服务时如何等待异步方法完成?
【发布时间】:2018-08-28 23:31:17
【问题描述】:

我已经看到了一些关于异步等待完成的现有问题,但是对我来说没有一个解决方案起作用。

我正在使用 C# 包装器连接到销售人员 https://github.com/developerforce/Force.com-Toolkit-for-NET/

在下面的方法中,我想等待方法 UsernamePasswordAsync 完成执行,以便我可以从 auth 对象中获取值。

public async Task<Token> GetTokenForSalesForce()
{
    Token token = null;
    try
    {
        var auth = new AuthenticationClient();
         await auth.UsernamePasswordAsync(configuration.Value.ClientId, configuration.Value.ClientSecert,
                                         configuration.Value.SFUsername, configuration.Value.SFPassword,
                                         configuration.Value.SFBaseUrl);
        if (!string.IsNullOrEmpty(auth.AccessToken) && !string.IsNullOrEmpty(auth.InstanceUrl))
        {
            token = new Token
            {
                BearerToken = auth.AccessToken,
                InstanceURL = auth.InstanceUrl,
                ApiVersion = auth.ApiVersion
            };
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
    return token;
}

public async Task<List<SFDashboardResponse>> GetOrderCountFromSalesForce(Token token)
{
    List<SFDashboardResponse> sFDashboardResponses = new List<SFDashboardResponse>();
    try
    {
        var client = new ForceClient(token.InstanceURL, token.BearerToken, token.ApiVersion);
        var response = await client.QueryAsync<SFDashboardResponse>("SELECT something ");
        var records = response.Records;
    }
    catch(Exception e)
    {

    }
    return sFDashboardResponses;
}

库中的签名是

public async Task WebServerAsync(string clientId, string clientSecret, string redirectUri, string code, string tokenRequestEndpointUrl)
{
}

问题是当方法等待等待首先执行时,另一个线程执行了原始调用者的另一部分。

我从这里调用它

public IActionResult post()
{
    var authtoken = _salesForceService.GetTokenForSalesForce();
    var response = _salesForceService.GetOrderCountFromSalesForce(authtoken.Result);
    DashboardModel dashboardModel = null;
    if (authtoken.Status == TaskStatus.RanToCompletion)
    {
       fill the object
    }

     return Ok(dashboardModel);
 }

【问题讨论】:

  • 我感谢那些对问题投反对票的人,如果你能说明理由就好了
  • 永远不要使用throw ex;,其中ex 是捕获的异常。您将丢失堆栈跟踪。只需执行throw;,它将保留堆栈跟踪。如果您唯一要做的就是重新抛出异常,请不要捕获异常。并且在您的代码中不要有一个空的 catch 块。至少,记录异常。
  • @mason 你是对的。记录器正在由另一个人实施。一旦完成,它将在 catch 块中使用。
  • 你不是在等待异步任务,所以代码当然会继续。这就是重点。

标签: c# asp.net-core async-await


【解决方案1】:

您可以在下面的任务中用Taskawait 包装IActionResult

public async Task<IActionResult> post()
{
    var authtoken = await _salesForceService.GetTokenForSalesForce();
    var response = await _salesForceService.GetOrderCountFromSalesForce(authtoken);

    DashboardModel dashboardModel = //fill the object

    return Ok(dashboardModel);
}

据我所知,至少这是您所要求的,如果有其他问题请告诉我。

编辑 1:

这只是我的建议/意见。

就我个人而言,我不太喜欢到处都用 try-catch 包裹代码,这样代码可能难以阅读和维护。你真的应该考虑将异常处理集中在一个地方,你可以有一个基本控制器或只是一个像这样的中间件:

public class ErrorHandlingMiddleware
{
    private readonly RequestDelegate _next;

    public ErrorHandlingMiddleware(RequestDelegate next)
    {
        this._next = next;
    }

    public async Task Invoke(HttpContext context, ILogger logger)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        { 
            await HandleExceptionAsync(context, ex, logger);
        }
    }

    private static Task HandleExceptionAsync(HttpContext context, Exception exception, ILogger logger) 
    {
        logger.Log(exception);
        //do something
        return context.Response.WriteAsync(... something ...); //Maybe some JSON message or something
    }
}

您只需在Configure 方法中将其注册为中间件,如下所示:

app.UseMiddleware<ErrorHandlingMiddleware>();

【讨论】:

    猜你喜欢
    • 2023-04-08
    • 2015-02-13
    • 1970-01-01
    • 2013-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-19
    • 2018-12-02
    相关资源
    最近更新 更多