gpt4 book ai didi

c# - 与 MS AsyncHelper 同步运行异步方法的空异常

转载 作者:行者123 更新时间:2023-11-30 15:26:48 46 4
gpt4 key购买 nike

由于您无法从子窗口 (@Html.Action) 调用运行异步方法,我一直在寻找从 运行 async 任务的最简单方法>非异步 方法。这将允许我的 MainMenu Controller Menu 操作在像这样注入(inject)时仍然有效(而不是必须移动到 VM 或 Ajax 解决方案):

<div class="row">
@Html.Action("MainMenu", "Menu")
</div>

我使用 MS 自己使用的代码副本尝试了这种有前途的方法:How to call asynchronous method from synchronous method in C#?

AsyncHelper 代码:

public static class AsyncHelper
{
private static readonly TaskFactory _myTaskFactory = new
TaskFactory(CancellationToken.None,
TaskCreationOptions.None,
TaskContinuationOptions.None,
TaskScheduler.Default);

public static TResult RunSync<TResult>(Func<Task<TResult>> func)
{
return AsyncHelper._myTaskFactory
.StartNew<Task<TResult>>(func)
.Unwrap<TResult>()
.GetAwaiter()
.GetResult();
}

public static void RunSync(Func<Task> func)
{
AsyncHelper._myTaskFactory
.StartNew<Task>(func)
.Unwrap()
.GetAwaiter()
.GetResult();
}
}

我是这样消费的:

    public async Task<ActionResult> MainMenu()
{
if (_currentCandidate == null)
{
throw new ArgumentNullException("_currentCandidate");
}
var candidateId = AsyncHelper.RunSync<int>(() => _currentCandidate.CandidateIdAsync());

[snip]
}

调用这个异步方法:

    public async Task<int> CandidateIdAsync()
{
var applicationUser = await this.ApplicationUserAsync();
if (applicationUser != null)
{
return applicationUser.CandidateId.GetValueOrDefault();
}
return 0;
}

只有当我运行它时,我才会收到以下错误:

enter image description here

我在这里错过了什么?代码看起来应该可以工作,但我对它还不够熟悉,无法弄清楚。

更新:

作为引用,MainMenu Controller 类如下所示:

public class MenuController : Controller
{
readonly ICurrentCandidate _currentCandidate;

public MenuController(ICurrentCandidate currentCandidate)
{
_currentCandidate = currentCandidate;
}

// GET: MainMenu
public ActionResult MainMenu()
{
if (_currentCandidate == null)
{
throw new ArgumentNullException("_currentCandidate");
}
var candidateId = AsyncHelper.RunSync<int>(() => _currentCandidate.CandidateIdAsync());

[snip]
return View(vm);
}
}

另一个更新:

失败似乎是在相关的 IF 代码中作为简化的 CandidateIdAsnyc 工作:

// This works
public async Task<int> CandidateIdAsync()
{
return 0;
}

这是该代码的其余部分:

public class CurrentCandidate : ICurrentCandidate
{
private readonly ApplicationDbContext _applicationDbContext;
private readonly IApplicationUserManager _userManager;
private readonly ICandidateStore _candidateStore;

public CurrentCandidate(ApplicationDbContext applicationDbContext, ICandidateStore candidateStore, IApplicationUserManager userManager)
{
this._candidateStore = candidateStore;
this._applicationDbContext = applicationDbContext;
this._userManager = userManager; // new ApplicationUserManager(new UserStore<ApplicationUser>(this._applicationDbContext));
}

public async Task<ApplicationUser> ApplicationUserAsync()
{
var applicationUser = await this._userManager.FindByIdAsync(HttpContext.Current.User.Identity.GetUserId());
return applicationUser;
}

public bool IsAuthenticated()
{
return HttpContext.Current.User.Identity.IsAuthenticated;
}

public async Task<int> CandidateIdAsync()
{
var applicationUser = await this.ApplicationUserAsync();
if (applicationUser != null)
{
return applicationUser.CandidateId.GetValueOrDefault();
}
return 0;
}
}

最佳答案

I have been searching for the simplest way to run async tasks from a non-async method.

这已被讨论过很多次,没有适用于所有场景的解决方案。内部 AsyncHelper 类型仅在 ASP.NET 团队知道它是安全的非常特殊的情况下使用;它不是通用解决方案。

一般来说,方法是:

  1. block (使用 ResultGetAwaiter().GetResult())。这种做法can cause deadlocks (正如我在我的博客上描述的那样)除非您始终使用 ConfigureAwait(false) - 并且您调用的所有代码也始终使用 ConfigureAwait(false)。但是,请注意您的代码不能使用ConfigureAwait(false),除非它实际上不需要 ASP.NET 上下文。
  2. 嵌套消息循环。这可以使用我的 AsyncEx 库中的 AsyncContext 之类的东西来实现。但是,有许多 ASP.NET API 隐式假定当前 SynchronizationContextAspNetSynchronizationContext,而 AsyncContext 中并非如此。
  3. 使用阻塞分离线程(使用 Task.Run(...).GetAwaiter().GetResult())。这种方法避免了您可以通过阻塞看到的死锁,但它确实在 ASP.NET 上下文之外执行代码。这种方法还会对您的可伸缩性产生负面影响(这首先是在 ASP.NET 上使用 async 的全部意义所在)。

换句话说,这些只是 hack。

ASP.NET vNext 有“ View 组件”的概念,可能是async,所以这将是 future 自然的解决方案。对于今天的代码,IMO 最好的解决方案是使方法同步;这比实现黑客攻击要好。

关于c# - 与 MS AsyncHelper 同步运行异步方法的空异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28679082/

46 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com