从非异步mvc控制器调用异步方法并返回变量

时间:2016-08-25 05:33:02

标签: asp.net-mvc asynchronous methods controller call

   public async Task<Utils.TReportReturn> GetReportDataColumnSettings(AdminTechnicianReportInput input)
    {
        input.CustomerId = m_customerId;
        input.UserId = m_userId;
        input.TimeOffset = m_timeOffset;
        TReportReturn objTReportReturn = new TReportReturn();
        objTReportReturn.ReportColumns = await new ReportsEntityContext().GetTechniciansReportColumns<AdminTechnicianReportInput>(input);
        objTReportReturn.ReportSettings = await new ReportsEntityContext().GetGeneralSettingsData<AdminTechnicianReportInput>(input);
        objTReportReturn.ReportData = await new ReportsDbContext().GetUserListDynamic<AdminTechnicianReportInput>(input);
        return objTReportReturn;
    }

public class HomeController : Controller
{
    public ActionResult Index()
    {
        AdminTechnicianReportInput objInput = new AdminTechnicianReportInput();
        objInput.CustomerId = 1;
        objInput.UserId = 5477;
        objInput.AddUpdateUserid = 0;
        objInput.intRowsPerPage = 200;
        objInput.intPageIndex = 0;
        objInput.intTarget = 0;
        objInput.intStatusId = 0;
        objInput.strSearchQuery = "";
        objInput.strSortColumn = "Id";
        objInput.strSortDirection = "ASC";


        var result = new ReportsModel(1, 5477, 0).Administration.AdminTechnicianReport.GetReportDataColumnSettings(objInput).Result;

        ViewBag.Title = result.ReportSettings.CustomerName + "__" + result.ReportSettings.PrintedOn;           

        return View();
    }

}

GetReportDataColumnSettings 函数调用许多异步方法,即模型库dll。

HomeController中的Index()方法是一个mvc方法,我希望在 result 变量中得到返回值。 Itried getawaiter()。getmethod(),但它没有工作。

我不喜欢将Index()方法更改为asynk Task。请提出另一种获得结果的方法

1 个答案:

答案 0 :(得分:2)

  

我不想将Index()方法更改为asynk Task。

为什么不呢?到目前为止 是最简单,最正确的解决方案。

第二个最简单的方法是让一切都同步。也就是说,如果你没有去async all the way,那就一直进行同步。

从同步代码调用异步有很多种方法可能会或可能不会在您的情况下工作;这些黑客都无处不在。有关详细信息,请参阅我的async brownfield article

在您的情况下,您最初的尝试是使用阻止黑客。为了在前核心ASP.NET上正常工作,您必须对整个方法调用树中的每个ConfigureAwait(false)使用await。这通常是可能的(当然,并不总是可行,因为库代码可能会或可能不会使用它),但它会导致维护问题(忘记一个,并且您已经遇到可能以死锁结束的竞争条件)。我在博客上详细解释why the deadlock happens

如果你不能一直异步,如果你不能一直同步,那么我推荐使用布尔同步参数Hack,它需要整个调用堆栈来支持同步异步调用者。对于您发布的代码,它看起来像这样:

private async Task<Utils.TReportReturn> DoGetReportDataColumnSettingsAsync(AdminTechnicianReportInput input, bool sync)
{
  input.CustomerId = m_customerId;
  input.UserId = m_userId;
  input.TimeOffset = m_timeOffset;
  TReportReturn objTReportReturn = new TReportReturn();
  objTReportReturn.ReportColumns = await new ReportsEntityContext().GetTechniciansReportColumns<AdminTechnicianReportInput>(input, sync);
  objTReportReturn.ReportSettings = await new ReportsEntityContext().GetGeneralSettingsData<AdminTechnicianReportInput>(input, sync);
  objTReportReturn.ReportData = await new ReportsDbContext().GetUserListDynamic<AdminTechnicianReportInput>(input, sync);
  return objTReportReturn;
}

private Task<Utils.TReportReturn> GetReportDataColumnSettingsAsync(AdminTechnicianReportInput input)
{ return DoGetReportDataColumnSettingsAsync(input, sync: false); }
private Utils.TReportReturn GetReportDataColumnSettings(AdminTechnicianReportInput input)
{ return DoGetReportDataColumnSettingsAsync(input, sync: true).GetAwaiter().GetResult(); }

具有此模式的密钥是,当该参数设置为sync时,采用true参数的任何方法都必须返回已完成的任务。