【问题标题】:async Task<object> function deadlock异步任务<object> 函数死锁
【发布时间】:2014-12-09 10:55:11
【问题描述】:
    public async Task<UserInfo> GetUserDataAsync(string NetworkID)
    {
        PrincipalContext principalcontext = new PrincipalContext(ContextType.Domain, ADDomain, ADUser, ADPass);
        UserPrincipal founduser = null;

        await Task.Run(() =>
        {
            founduser = UserPrincipal.FindByIdentity(principalcontext, IdentityType.SamAccountName, NetworkID);
        });

        //task.Wait();

        return founduser != null && founduser.Enabled == true ?
            new UserInfo
            {
                DisplayName = founduser.DisplayName,
                Email = founduser.EmailAddress,
                NetworkID = founduser.SamAccountName
            } : new UserInfo();
    }

这是一个假设通过广告验证用户的功能,我可以使用 Task task = Task.Factory.StartNew (() => {});和 task.Wait();但这仍然会同步运行该功能。使用 async 和 await 运行上面的代码会使浏览器陷入死锁,永远旋转并且永远不会返回值。

【问题讨论】:

  • 为什么还要在任务中获取 UserPrincipal 呢?
  • @Ananke,你建议用什么?
  • 我想我要从这个函数中移除 async 和 await 并且只使用 task.factory.startnew 功能来执行这个操作。除非其他人有其他想法?
  • 我的建议是为什么不同步调用它呢? UserPrincipal.FindByIdentity 本质上不是异步的。
  • @SamHaider 但我们要问的是为什么要使用任务。您所做的只是增加开销。只需执行founduser = UserPrincipal.FindByIdentity(principalcontext, IdentityType.SamAccountName, NetworkID); 并完全放弃任务。

标签: c# asynchronous async-await


【解决方案1】:

如果要异步执行,为什么不直接返回任务呢?

public Task<UserInfo> GetUserDataAsync(string NetworkID)
{
    return Task.Run(() =>
    {
        PrincipalContext principalcontext = new PrincipalContext(ContextType.Domain, ADDomain, ADUser, ADPass);
        UserPrincipal = UserPrincipal.FindByIdentity(principalcontext, IdentityType.SamAccountName, NetworkID);


        return founduser != null && founduser.Enabled == true ?
          new UserInfo
          {
            DisplayName = founduser.DisplayName,
            Email = founduser.EmailAddress,
            NetworkID = founduser.SamAccountName
          } : new UserInfo();
    });
}

【讨论】:

  • 谢谢,我只是要在 Task.Run 之前添加 async 和 await 就可以了...
【解决方案2】:

这就是我最终对同步调用所做的事情。

Task task = Task.Factory.StartNew(() =>
            {
                founduser = UserPrincipal.FindByIdentity(principalcontext,IdentityType.SamAccountName, NetworkID);
            });

            task.Wait();

【讨论】:

  • 您仍在(不必要地)使用任务恕我直言。只需写founduser = UserPrincipal.FindByIdentity(...) 而不是上面的五行。
  • 他知道上面的版本很傻。他想知道为什么他的问题中的版本(使用await)似乎永远不会完成,而上面的阻塞版本却成功完成,尽管两者都使用Task 来调用FindByIdentity
猜你喜欢
  • 2018-02-13
  • 2019-01-13
  • 1970-01-01
  • 2020-04-25
  • 2014-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多