在异步进行同步调用时如何返回TaskStatus?

时间:2016-09-14 09:05:30

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

我有一个旧的数据访问库,我需要在我的ASP.NET MVC应用程序中使用,但是我很难将它带入MVC世界,因为许多服务器端操作都应该是异步的。我的数据访问库看起来像这样:

public class MyOldDAL
{
    public TaskResult CreateUser(string userName)
    {
        try
        {
            // Do user creation
            return new TaskResult { Success = true, Message = "success" };
        }
        catch (Exception ex)
        {
            return new TaskResult { Success = false, Message = ex.Message };
        }
    }
}

由我的MVC应用程序调用,如下所示:

public class MyUserStore : IUserStore<ApplicationUser>
{
    private readonly MyOldDAL _dal = new MyOldDAL();
    public async Task CreateAsync(ApplicationUser user)
    {
        await Task.Run(() => _dal.CreateUser(user.UserName));
    }
}

Task.Run()中的方法出于某种原因失败之前,这是正常的。如果TaskStatus.Faulted错误,我希望能够返回TaskResult.Success,但我无法在线找到如何正确操作的示例 - 我所有的Google搜索结果都是如何使用Task<T>接口不允许的IUserStore

对于记录,我希望我能改变MyOldDAL - 它的目标是.NET 3.5,所以没有async或{{1}那里!

2 个答案:

答案 0 :(得分:3)

报告任务错误的正常方法是通过例外,因此您只需要自己进行转换:

public class MyUserStore : IUserStore<ApplicationUser>
{
  private readonly MyOldDAL _dal = new MyOldDAL();
  public Task CreateAsync(ApplicationUser user)
  {
    var result = _dal.CreateUser(user.UserName);
    if (result.Success)
      return Task.CompletedTask;
    return Task.FromException(new InvalidOperationException(result.Message));
  }
}

请注意,Task.Run

答案 1 :(得分:1)

注意:正如Stephen Cleary在回答中所说,Task.Run

原始答案(评论前): 您的CreateAsync方法通常应该是这样的:

public async Task<TaskResult> CreateAsync(ApplicationUser user)
{
    return await Task.Run(() => _dal.CreateUser(user.UserName));
}

但是,如果您无法从Task<TaskResult>方法返回CreateAsync ......那么,根据定义,您无法从TaskResult获取CreateAsync。在这种情况下,您可以在本地存储结果:

private TaskResult taskResult;

public async Task CreateAsync(ApplicationUser user)
{
    var result = await Task.Run(() => _dal.CreateUser(user.UserName));
    this.taskResult = result;
    // process taskResult wherether you need
}

或者使用TaskResult有效负载引发事件,允许MyUserStore的客户订阅此事件:

public event EventHandler<TaskResult> TaskCompleted;

public async Task CreateAsync(ApplicationUser user)
{
    var result = await Task.Run(() => _dal.CreateUser(user.UserName));
    this.OnTaskCompleted(result);
}

private void OnTaskCompleted(TaskResult result)
{
    this.TaskCompleted?.Invoke(this, result);
}