异步方法不返回

时间:2014-08-28 12:00:26

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

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

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;
    }  
}

2 个答案:

答案 0 :(得分:5)

您的问题有两个部分。

首先是僵局。您需要使用Task.Wait替换所有Task<T>.Resultawait来电。我更充分地解释了这种死锁情况on my blogin the answer you linked to

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

答案 1 :(得分: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");的调用没有等待,因此在return View(model);有机会完成之前继续调用plane.GetSuggestions("ISTANBUL");

我认为这就是为什么你没有得到预期的结果。