【问题标题】:Async Method Doesn't Return异步方法不返回
【发布时间】:2014-10-22 06:51:01
【问题描述】:

我有以下使用Scanner 类的Action 方法,该类使用一些网络服务来获取一些数据。当我在GetSuggestions 方法中使用断点时,我可以看到结果。但是,这些数据永远不会返回到我的 Action 方法。相反,当我在Index() 中检查model 的值时,它是,

Id = 1, Status = System.Threading.Tasks.TaskStatus.WaitingForActivation, Method = "{null}", Result = "{Not yet computed}"

我检查了this 问题,但它没有帮助我。

控制器动作方法:

[HttpGet]
public ActionResult Index()
{
    var plane = new Scanner();
    var model = plane.GetSuggestions("ISTANBUL");

    return View(model);
}

GetSuggestions 方法:

public async Task<List<PlaceDto>> GetSuggestions(string key)
{
    string url = String.Format("URL GOES HERE", key, API_KEY);

    string data = await RequestProvider.Get(url);

    return JObject.Parse(data).SelectToken("Places").ToObject<List<PlaceDto>>();
}

RequestProvider 方法:

public static async Task<string> Get(string url)
{
    using (var client = new HttpClient())
    {
        return await client.GetStringAsync(url);
    }
}

编辑 1

我还尝试用任务包装 Action 方法并等待 GetSuggestions 方法,但我在 client.GetStringAsync(url) 收到异常

我在操作方法上使用任务时出现异常

System.NullReferenceException was unhandled
  HResult=-2147467261
  Message=Object reference not set to an instance of an object.
  Source=System.Web
  StackTrace:
       at System.Web.ThreadContext.AssociateWithCurrentThread(Boolean setImpersonationContext)
       at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)
       at System.Web.LegacyAspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback callback, Object state)
       at System.Web.LegacyAspNetSynchronizationContext.CallCallback(SendOrPostCallback callback, Object state)
       at System.Web.LegacyAspNetSynchronizationContext.Post(SendOrPostCallback callback, Object state)
       at System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation.PostAction(Object state)
       at System.Threading.Tasks.AwaitTaskContinuation.RunCallback(ContextCallback callback, Object state, Task& currentTask)
    --- End of stack trace from previous location where exception was thrown ---
       at System.Threading.Tasks.AwaitTaskContinuation.<ThrowAsyncIfNecessary>b__1(Object s)
       at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
       at System.Threading.ThreadPoolWorkQueue.Dispatch()
       at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
  InnerException: 

编辑 2

我从 await client.GetStringAsync(url); 中删除了 await 关键字,并且代码可以正常工作。但是,我认为这将同步运行而不是异步运行。以下是更新后的Get方法,

public static async Task<string> Get(string url)
{
    using (var client = new HttpClient())
    {
        return client.GetStringAsync(url).Result;
    }  
}

【问题讨论】:

  • GetSuggestions 的返回类型为Task,您必须调用.Result 才能获得所需的List&lt;PlaceDto&gt;。
  • 内部异常堆栈跟踪是什么?
  • @MarcelN。内部异常为空。
  • @emrenevayeshirazi:除了 Jason 的回答之外,您还需要将操作签名更改为 public async Task&lt;ActionResult&gt; Index()。不确定你是否已经这样做了。
  • @MarcelN。谢谢,但我已经尝试过了。请参阅我的 1. 和 2. 编辑。

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


【解决方案1】:

你的问题有两个部分。

首先是死锁。您需要将任何Task.Wait 或Task&lt;T&gt;.Result 调用替换为await。我更全面地解释了这种死锁场景on my blog 和in the answer you linked to。

第二个是例外。您看到此异常是因为您在 ASP.NET 4.0 上使用 async/await,这是不受支持的。您需要确保您的目标是 .NET 4.5 和 you have set &lt;httpRuntime targetFramework="4.5" /&gt; in your web.config。

【讨论】:

  • 我尝试到处等待,但没有成功。我检查了我所有的项目属性,它们都设置为 .NET 4.5 但是,在我的一个项目中,我有这条线。 会不会是这个问题?
  • 不,这很正常。您绝对确定httpRuntime 元素具有正确的targetFramework?
  • 我有 但我也将 targetFramework="4.5" 添加到 中。当我到达 return await client.GetStringAsync(url);调试时,没有任何反应,我在页面上看到 System.Threading.Tasks.Task`1[System.Web.Mvc.ActionResult]。
  • 更新所有 NuGet 包。您正在运行一个非常旧版本的 MVC。
【解决方案2】:

我认为你需要等待plane.GetSuggestions("ISTANBUL");的电话

[HttpGet]
public async Task<ActionResult> Index()
{
    var plane = new Scanner();
    var model = await plane.GetSuggestions("ISTANBUL");

    return View(model);
}

当您调试代码时,它可能会按预期运行,因为您正在单步执行代码。但是,一旦您让代码自然运行,因为对 plane.GetSuggestions("ISTANBUL"); 的调用不会在等待,因此会继续并在 plane.GetSuggestions("ISTANBUL"); 有机会完成之前调用 return View(model);。

我认为这就是您没有得到预期结果的原因。

【讨论】:

  • 我试过了,但是当我这样做时,我得到了 Object ref。未设置为实例...返回时出现异常 await client.GetStringAsync(url);我用异常详细信息编辑了我的问题
猜你喜欢
  • 1970-01-01
  • 2013-05-03
  • 2012-12-20
  • 2018-06-10
  • 1970-01-01
  • 2019-01-08
  • 2012-09-05
  • 2014-09-22
  • 1970-01-01
相关资源
最近更新 更多