简体   繁体   中英

Async Method Doesn't Return

I have the following Action method that uses Scanner class which uses some webservice to get some data. When I use breakpoint inside GetSuggestions method, I can see the result. However, this data is never returned to my Action method. Instead when I check the value of model inside Index() , it is,

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

I checked this question but It did not helped me.

Controller Action Method:

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

    return View(model);
}

GetSuggestions Method :

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 Method :

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

Edit 1

I also tried wrapping the Action method with task and waiting on GetSuggestions method but I receive exception on client.GetStringAsync(url)

Exception When I use Task on Action Method

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: 

Edit 2

I removed the await keyword from await client.GetStringAsync(url); and code works. However, I think this will run synchronously not async. Following is the updated Get method,

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

There are two parts to your problem.

The first is the deadlock. You need to replace any Task.Wait or Task<T>.Result calls with await . I explain this deadlock scenario more fully on my blog and in the answer you linked to .

The second is the exception. You're seeing this exception because you're using async / await on ASP.NET 4.0, which is not supported. You need to ensure that you're targeting .NET 4.5 and that you have set <httpRuntime targetFramework="4.5" /> in your web.config .

I think you need to await on the call to plane.GetSuggestions("ISTANBUL");

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

    return View(model);
}

When you're debugging the code, it likely is wokring as expected, since you are stepping through the code. Howver, once you let the code run naturally, since the call to plane.GetSuggestions("ISTANBUL"); is not awaiting, and thus goes ahead and calls return View(model); before plane.GetSuggestions("ISTANBUL"); has had a chance to finish.

I think that's why you're not getting the expected result.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM