Asp.net MVC4Web应用程序中对webservice的异步调用

Asp.net MVC4Web应用程序中对webservice的异步调用,asp.net,asp.net-mvc-4,webservice-client,Asp.net,Asp.net Mvc 4,Webservice Client,我正在构建我的第一个真正的MVC4应用程序,我遇到了以下问题 我有一个“用户”类的模型。它的数据通过对webservice的异步调用获得: public sealed class AdminDMSEntities { public List<User> UserList { get; private set; } public AdminDMSEntities() { this.UserList = new List<User>(

我正在构建我的第一个真正的MVC4应用程序,我遇到了以下问题

我有一个“用户”类的模型。它的数据通过对webservice的异步调用获得:

public sealed class AdminDMSEntities
{
    public List<User> UserList { get; private set; }

    public AdminDMSEntities()
    {
        this.UserList = new List<User>(0);
        ServiceClient client = new ServiceClient();
        client.GetUsersCompleted += (s, e) => 
        {
            if (e.Result == null)
                throw new ArgumentNullException("No users were retrieved");

            UserList = new List<User>(0);
            e.Result.ForEach(w => this.UserList.Add(new User(w.Guid, w.TrusteeType, w.Username, w.Email, w.LastLogin, w.PasswordChanged, w.IsUsingTempPassword)));               
        };

        client.GetUsersAsync();
    }        
}
问题是,我将以InvalidOperationException结束,因为控制器并没有等待异步调用完成,而是在正确填充用户之前将UserList传递给视图

我可以暂时让调用同步,但很可能以后我会被迫使用异步调用,所以我想知道如何确保控制器在将UserList传递给view之前等待异步调用完成

提前谢谢

编辑:我已尝试使用AsyncController的方法,如下所示,目前我已将其添加到AdminDMS实体类中:

public static async Task<AdminDMSEntities> AdminDMSEntitiesAsync()
    {
        AdminDMSEntities result = null;
        Task<AdminDMSEntities> getUsersAsyncTask = Task.Factory.StartNew(() => new AdminDMSEntities());
        await getUsersAsyncTask;
        return result;
    }
公共静态异步任务AdminsEntitiesAsync()
{
AdminDMSEntities结果=null;
Task getUsersAsyncTask=Task.Factory.StartNew(()=>newadmindmsentities());
等待getUsersAsyncTask;
返回结果;
}
这是对控制器的更改:

public class UsersController : AsyncController
{
    private AdminDMSEntities adminEntities = null;
    //
    // GET: /User/

    public async Task<ActionResult> Index()
    {
        if (adminEntities == null)
        {
            adminEntities = await AdminDMSEntities.AdminDMSEntitiesAsync();
        }
        return View(adminEntities.UserList);
    }
}
公共类UsersController:AsyncController
{
private AdminDMSEntities adminEntities=null;
//
//获取:/User/
公共异步任务索引()
{
如果(adminEntities==null)
{
adminEntities=等待AdminDMSEntities.AdminDMEntitiesAsync();
}
返回视图(adminEntities.UserList);
}
}
结果是adminEntities包含类的实例,但列表中没有用户(应该有11个)

EDIT2:因为有人告诉我创建新任务不是正确的做法,所以我采用了第一种建议的方法从代码中删除AdminDMSEntities类。我感谢达林帮了我的忙:)

你可以用一个电话。其思想是让控制器从类派生,而不是从
控制器
类派生。此类提供了允许您执行异步操作的方法

例如:

public class MyController: AsyncController
{
    public void IndexAsync()
    {
        AsyncManager.OutstandingOperations.Increment();
        var client = new SomeClient();
        client.GetUsersCompleted += (s, e) => 
        {
            UserList = new List<User>();
            AsyncManager.Parameters["users"] = e.Result.Select(
                w => new User(
                    w.Guid, 
                    w.TrusteeType, 
                    w.Username, 
                    w.Email, 
                    w.LastLogin, 
                    w.PasswordChanged, 
                    w.IsUsingTempPassword
                )
            )
            .ToList();
            AsyncManager.OutstandingOperations.Decrement();            
        };
        client.GetUsersAsync();
    }

    public ActionResult IndexCompleted(IEnumerable<User> users)
    {
        return View(users);
    }
}
你可以用一个。其思想是让控制器从类派生,而不是从
控制器
类派生。此类提供了允许您执行异步操作的方法

例如:

public class MyController: AsyncController
{
    public void IndexAsync()
    {
        AsyncManager.OutstandingOperations.Increment();
        var client = new SomeClient();
        client.GetUsersCompleted += (s, e) => 
        {
            UserList = new List<User>();
            AsyncManager.Parameters["users"] = e.Result.Select(
                w => new User(
                    w.Guid, 
                    w.TrusteeType, 
                    w.Username, 
                    w.Email, 
                    w.LastLogin, 
                    w.PasswordChanged, 
                    w.IsUsingTempPassword
                )
            )
            .ToList();
            AsyncManager.OutstandingOperations.Decrement();            
        };
        client.GetUsersAsync();
    }

    public ActionResult IndexCompleted(IEnumerable<User> users)
    {
        return View(users);
    }
}

它看起来像我需要的,但我无法让它运行。我的GetUsersAsync方法来自自动生成的服务引用,它返回“void”,所以我在我的原始帖子中使用了构造函数中的代码,我必须使用
wait task.Factory.StartNew(()=>client.GetUsersAsync())创建任务非起始null仍在传递给视图。不应创建新任务。您应该在控制器操作中直接使用自动生成的客户端实例。然后订阅
GetUsersCompleted
事件,如我的回答所示。我删除了前面的评论,我刚刚找到了自动生成方法的定义。我将尝试您的方法,然后再与您联系。我查看了定义,自动生成的方法只返回“void”。所以我试着在我原来的帖子里用“编辑”这个词。不过,最好使用异步方法返回用户数组或用户列表,然后我可以使用异步方法接受您的建议。现在我将尝试第一种解决方案第一种解决方案工作正常。但我更喜欢async Wait解决方案,我需要弄清楚如何更改服务的方法来尝试它。它看起来像我需要的,但我无法让它运行。我的GetUsersAsync方法来自自动生成的服务引用,它返回“void”,所以我在我的原始帖子中使用了构造函数中的代码,我必须使用
wait task.Factory.StartNew(()=>client.GetUsersAsync())创建任务非起始null仍在传递给视图。不应创建新任务。您应该在控制器操作中直接使用自动生成的客户端实例。然后订阅
GetUsersCompleted
事件,如我的回答所示。我删除了前面的评论,我刚刚找到了自动生成方法的定义。我将尝试您的方法,然后再与您联系。我查看了定义,自动生成的方法只返回“void”。所以我试着在我原来的帖子里用“编辑”这个词。不过,最好使用异步方法返回用户数组或用户列表,然后我可以使用异步方法接受您的建议。现在我将尝试第一种解决方案第一种解决方案工作正常。但我更喜欢AsyncWait解决方案,我需要弄清楚如何更改服务的方法来尝试它。
public class MyController: AsyncController
{
    public async Task<ActionResult> Index()
    {
        var client = new SomeClient();
        var users = await client.GetUsersAsync().Select(
            w => new User(
                w.Guid, 
                w.TrusteeType, 
                w.Username, 
                w.Email, 
                w.LastLogin, 
                w.PasswordChanged, 
                w.IsUsingTempPassword
            )
        )
        .ToList();
        return View(users);
    }
}