转换方法以使用异步

Convert a method to use async

我正在转换身份验证过程以支持异步,VS 2015 IDE 警告我以下消息: 异步方法缺少 'await' 运算符,将 运行 同步... 等...

无论如何,代码连接到 LDAP 存储并验证用户的帐户等... 我用 await 尝试了各种方法,但我只是在这里遗漏了一些东西。我将代码恢复到原来的状态。我将不胜感激任何让它正确支持异步的指导......

代码如下:

public async Task<User> GetAsyncADUser(PrincipalContextParameter param)
    {
        try
        {

            if (UseLDAPForIdentityServer3)
            {
                using (var pc = new PrincipalContext(ContextType.Domain, param.ADDomain, param.ADServerContainer, param.ADServerUser, param.ADServerUserPwd))
                {
                    UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(pc, param.UserNameToValidate);
                    if (userPrincipal != null)
                    {
                        bool isvalid = pc.ValidateCredentials(userPrincipal.DistinguishedName, param.UserPasswordToValidate, ContextOptions.SimpleBind);

                        if (isvalid)
                        {
                            User user = new User { ad_guid = userPrincipal.Guid.ToString(), Username = param.UserNameToValidate, Password = param.UserPasswordToValidate };
                            return user;
                        }
                    }
                }
            }

        }
        catch (Exception ex)
        {
            throw;
        }

        return null;

    }

正如它所说,您的代码是同步的。如果你将 UserPrincipal.FindByIdentityPrincipalContext.ValidateCredentials 做的任何事情包装在一个任务中,然后 return 那个,那么你可以让它异步工作。

正如 Stephen Cleary 的评论所说,如果有较低级别,您可以异步执行工作,在那里执行并将 async/await 传递到此级别。虽然不知道这些方法是什么样子,但很难说。

public Task<UserPrincipal> FindByIdentity (PrincipalContext pc, string username)
    {
        return Task.Run(() =>
        {
            // Do the thing;
        });
    }

这将允许您等待它们并且您的代码将是异步的。

public async Task<User> GetADUserAsync(PrincipalContextParameter param)
    {
        try
        {
            if (UseLDAPForIdentityServer3)
            {
                using (var pc = new PrincipalContext(ContextType.Domain, param.ADDomain, param.ADServerContainer, param.ADServerUser, param.ADServerUserPwd))
                {
                    UserPrincipal userPrincipal = await UserPrincipal.FindByIdentity(pc, param.UserNameToValidate);
                    if (userPrincipal != null)
                    {
                        bool isvalid = await pc.ValidateCredentials(userPrincipal.DistinguishedName, param.UserPasswordToValidate, ContextOptions.SimpleBind);

                        if (isvalid)
                        {
                            User user = new User { ad_guid = userPrincipal.Guid.ToString(), Username = param.UserNameToValidate, Password = param.UserPasswordToValidate };
                            return user;
                        }
                    }
                }
            }

        }
        catch (Exception ex)
        {
            throw;
        }

        return null;

    }

来自MSDN

以下特征总结了构成异步方法的要素:

  • 方法签名包含异步修饰符。
  • 按照惯例,async 方法的名称以 "Async" 后缀结尾。 return 类型是以下类型之一:

    • Task<TResult> 如果您的方法有一个 return 语句,其中操作数的类型为 TResult.
    • Task 如果您的方法没有 return 语句或有一个没有操作数的 return 语句。
    • Void 如果您正在编写异步事件处理程序。
  • 该方法通常包含至少一个 await 表达式,它标记了等待的异步操作完成之前该方法无法继续的点。同时,该方法被挂起,并将控制 returns 交给该方法的调用者。本主题的下一部分说明了在暂停点发生的情况。

您可以使用 return Task.Run(() => { /* your code here */ }) 和 return 和 Task<User>。然后您可以将此方法称为:

User user = await GetAsyncADUser();

这样就不需要在方法GetAsyncADUser中使用async关键字了,但是需要在使用上面这行代码的方法中标记[=11] =]关键字。

try catch 块可以保留....要运行 代码异步,只需将其放在Task.Run:

内的一个动作中
public async Task<User> GetAsyncADUser(PrincipalContextParameter param)
{        
    if (UseLDAPForIdentityServer3)
    {
        return await Task.Run() =>
        {
            using (var pc = new PrincipalContext(ContextType.Domain, param.ADDomain, param.ADServerContainer, param.ADServerUser, param.ADServerUserPwd))
            {
                UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(pc, param.UserNameToValidate);
                if (userPrincipal != null)
                {
                    bool isvalid = pc.ValidateCredentials(userPrincipal.DistinguishedName, param.UserPasswordToValidate, ContextOptions.SimpleBind);

                    if (isvalid)
                    {
                        User user = new User { ad_guid = userPrincipal.Guid.ToString(), Username = param.UserNameToValidate, Password = param.UserPasswordToValidate };
                        return user;
                    }
                }
            }
        }
    }
    return null;
}

在此代码块中似乎没有等待等待的异步调用....我的意思是,没有方法调用 returns 任务。

例如,如果方法 UserPrincipal.FindByIdentity() 是一个异步方法,(returns Task<UserPrincipal>) 那么它可以像这样等待:

UserPrincipal userPrincipal = await UserPrincipal.FindByIdentity();

但是,它不是异步方法,因此没有什么可等待的。您可以在这里做的一件事是将您想要 运行 的代码异步包装在辅助方法中,通过 Task.Run(() => RunMeAsync()); 执行该辅助方法并等待您刚刚开始的新任务的结果。

var result = await Task.Run(() => RunMeAsync());

其中 RunMeAsync() 是您想要异步 运行 的辅助方法。