帮助需要 - C#异步方法 [英] C# asynchronous method - help needed

查看:100
本文介绍了帮助需要 - C#异步方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有使用Web API操作的异步方法。这似乎是停留在一个循环。我对这种推理是因为如果我把catch块的第一行一个破发点,并步入,它从来没有真正命中的第二行。

I have an asynchronous method that consumes a Web API action. It appears to be stuck in a loop. My reasoning for this is because if I put a break point on line 1 of the catch block, and step into, it never actually hits the second line.

我最初用回10万+(30MB〜)行的数据集,并认为它可能只是缓慢,由于请求的大小,但改变我的Web API操作后只返回1行仍然存在问题。这些数据肯定是被返回,当我浏览到我得到JSON在我的浏览器返回的网页API解决方案的URI。

I was initially returning a data set with 100,000+ (~30mb) rows and thought that it could just be slow due to the size of the request, but after changing my Web API action to return only 1 row the problem still persisted. The data is definitely being returned as when I browse to the URI of the Web API solution I'm getting JSON returned in my browser.

public async Task<IEnumerable<Document>> GetAll()
{
    try
    {
        var response = await _client.GetAsync(
                       string.Format("{0}/api/document", _baseURI));

        // never hits line below
        return await response.Content.ReadAsAsync<Document>() 
                   as IEnumerable<Document>;
    }
    catch (Exception ex)
    {
        // handle exception
    }
}

我不知道如果我失去了一些东西?有些帮助将是AP preciated。

I'm not sure if I'm missing something here? Some help would be appreciated.

修改1

在回应一些问题,我有一个是由一个MVC项目中引用一个Web API项目。我不得不做出从原来的问题的一些变化对JSON反序列化。

In response to some questions, I have a Web API project that's referenced by a MVC project. I've had to make some changes from original question for JSON deserialization.

存储库:

public async Task<IEnumerable<Document>> GetAll()
{
    try
    {
        string json;
        var response = await _client.GetAsync(string.Format(
                       "{0}/api/document", _baseURI)).ConfigureAwait(false);

        var resource = await response.Content.ReadAsAsync<Document>();

        using(var reader = new StreamReader(resource.ToString()))
        {
            json = reader.ReadToEndAsync().ToString();
        }

        return JsonConvert.DeserializeObjectAsync<Document>(json) 
                       as IEnumerable<Document>;
        }
        catch (Exception)
        {
            throw;
        }
    }

控制器:

public async Task<ActionResult>  GetAll()
{
    return PartialView("_GetAllDocumentsPartial", await _docRepo.GetAll());
}

通过以​​下答案中描述的变化,同样的问题依然如上述调试时发生。不过,我得到任务被取消了。例外在资源库中​​的方法渔获物。

With changes described in answers below, the same problem still occurs when debugging as above. However I get "A task was canceled." exception on the catch in the method in the repository.

堆栈跟踪。

推荐答案

你叫 GETALL()。从ASP.NET应用程序的结果?既然你已经标记为MVC这个问题,我认为如此。如果这样做,那么你就死锁自己。

Are you calling GetAll().Result from an ASP.NET application? Since you have tagged MVC to this question, I assume so. If you do, then you are deadlocking yourself.

假设你调用Web API是这样的。

Say you calling web API like this.

public ActionResult Index()
{
    var result = GetAll().Result;

    return View();
}

这里的问题是异步调用完成时,它需要继续原来的线程在那里蹦出来的,但你可以通过调用结果阻塞线程()。呼吁对结果的异步调用块,并等待返回和异步延续等待的ASP.NET线程可继续进行。这是一个死循环。

The problem here is when the async call completes, it needs to continue on the original thread where it jumped out but you are blocking that thread by calling Result(). Call to Result blocks and waits for async call to return and the async continuation waits for the ASP.NET thread to be available to continue. That is a dead lock.

更改GETALL()这样的。

Change your GetAll() like this.

public async Task<IEnumerable<Document>> GetAll()
{
    try
    {
        var response = await _client.GetAsync(
                       string.Format("{0}/api/document", _baseURI))
                           .ConfigureAwait(false);

        // never hits line below
        return await response.Content.ReadAsAsync<Document>() 
                   as IEnumerable<Document>;
    }
    catch (Exception ex)
    {
        // handle exception
    }
}

这表示上下文不必是preserved异步调用完成,因此继续发生在一个线程池线程(而不是ASP.NET)。

This indicates the context need not be preserved when the async call is complete and hence the continuation happens in a thread pool thread (not ASP.NET).

更重要的是改变操作方法公共异步任务&LT;&的ActionResult GT;指数()并等待 GETALL()

Better yet change the action method to public async Task<ActionResult> Index() and await GetAll().

如果您认为此答案有帮助,您只能感谢斯蒂芬克利

If you find this answer helpful, you must only thank Stephen Cleary.

这篇关于帮助需要 - C#异步方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆