【问题标题】:How to use async and await in C#?如何在 C# 中使用 async 和 await?
【发布时间】:2016-07-21 05:29:26
【问题描述】:

在这里,我正在检查属性是否已迁移或正在进行中,如果正在进行中,那么我不想等待来自提供的 URL 的 Web Response 消息,因此 HttpPost 方法应该在后台运行 和calling method 应该同时执行它的任务。 为了实现这个功能,我在下面的方法中使用了asyncawait

以下是从 URL 发布和获取 XML 响应的方法:

public static async Task<string> HttpPost(string url, string message, bool ignoreResponse = false)
{
    string lcPostData = null;
    string _XmlResponse = string.Empty;
    try
    {            
        using (var client = new HttpClient())
        {
            var httpContent = new StringContent(message, Encoding.UTF8, "application/xml");
            var SupplierLinkUri = new Uri(url);

            if (!ignoreResponse)
            {                    
                var httpResponseMessage = await client.PostAsync(SupplierLinkUri, httpContent);

                if (httpResponseMessage.StatusCode == HttpStatusCode.OK)
                    _XmlResponse =  httpResponseMessage.Content.ReadAsStringAsync().Result;
            }
            else if (ignoreResponse && !(isReservation(message)))   //message.Contains("Reservation"))
            {       
                /* I want below lines of code to run asynchronously (i.e. Run in background) So I used Task & await but it fails*/
                Task<HttpResponseMessage> httpPostTask = client.PostAsync(SupplierLinkUri, httpContent);
                HttpResponseMessage asyncPost = await httpPostTask;                 
            }
        }       
    }
    catch (Exception e)
    {       
    }
    return _XmlResponse;
}

上述方法运行没有错误,但我想知道这是否是在 C# 中使用 asyncawait 的正确方法, 我需要在任何地方修改我的代码还是按照上述要求正确?

else-if 中的await 部分不起作用。根据文档,这应该运行asynchronously,即在后台运行,但目前不是。

任何人都可以检查并提出代码中的问题吗?

他们有更好的方法来实现这一点吗?

感谢任何建议和想法!感谢您的帮助!

【问题讨论】:

  • 如果您从服务器获取块中的 xml,除非修改服务器代码,否则您实际上无法将数据作为连续数据获取。在块中获取数据可能比获取可能导致内存异常的一大块数据更有效。巨大的 xml 文件通常会导致内存异常,然后您需要使用 xmlreader 以您现在的方式有效地读取块中的 xml。
  • 你想在这里做什么 - 究竟是什么问题?如果问题是在任务返回之前您没有从该方法获得响应,那么这是可以预期的。
  • @Paddy :问题是我使用await 在后台运行client.PostAsync(SupplierLinkUri, httpContent); 在其他部分按照文档但它是同步运行的。
  • 如何检查它是否同步运行?您可能希望在您的 Common.HttpPost btw 前面包含一个“等待”。
  • @Paddy:我们在那个 url 上有测试应用程序,我们发布像 Task&lt;HttpResponseMessage&gt; httpPostTask = client.PostAsync(SupplierLinkUri, httpContent); HttpResponseMessage waitPost = await httpPostTask; // This is not working why? 这样的数据,然后当我们调试两个应用程序时,控件从这一行开始并停留在另一个名为方法的应用程序上。但我希望它返回并在后台运行第二个应用程序,因为我使用了await,但它似乎无法正常工作。

标签: c# web-services async-await httpclient


【解决方案1】:

好的 - 这不是 async/await 的用途 - 当您等待时,您调用的方法在另一个线程(不是 UI 线程)上运行,并将控制权返回给您的 main 方法(通过后台的延续) ) 完成后。

在异步调用完成之前,您“等待”的方法不会返回其结果。

例如

async Task<int> A()
{
    return await B();
}

async Task<int> B()
{
     //Call to a long running service to get your answer, e.g.
    return  await PostToClientAsynchronously();
}

//Event handler on front end.
async void SomeButton_Click() {
    txtBox1.Text = await A();
}

在上面的示例中,PostToClientAsynchronously 将在另一个线程(不是 UI 线程)上运行,但直到帖子完成后,控件才会返回以设置事件处理程序中的文本框值。

我想为您自己的代码发布一个示例,但老实说,我不确定您想要做什么。我怀疑这个问题可以通过将异步方法扩展到您的 UI 来解决,因此不会阻止它并允许其他操作,但我不确定。

关于调用 async/await 方法的另一个重要的事情是所有方法(从前端向下)都需要标记为异步,以允许正确等待。


听起来您正在尝试将这些作为“即发即弃”类型的方法运行,但只有当您所做的事情没有返回您随后需要采取行动的信息并且您确定任何可能发生的异常都不会损害您的应用程序。遇到的任何异常都不会冒泡到您的应用程序中。

真正的“一劳永逸”用例很少见。


更多关于为什么在异步编程时必须“乌龟一路下降”的信息:

https://msdn.microsoft.com/en-us/magazine/jj991977.aspx

有关“一劳永逸”的更多信息(请务必阅读上一篇文章中有关“避免异步无效”的部分:

Fire and Forget approach

【讨论】:

  • 非常感谢您的详细解释!
  • await 不会在后台线程上运行方法,也不一定会在原始线程上恢复(在这种情况下,它通常不会)。此外,ASP.NET 应用程序中没有 UI 线程。
  • @StephenCleary - 抱歉,帖子不清楚这个电话是从哪里发出的。我知道 ASP.net 中没有 UI 线程,并且没有提到它在 same 线程上恢复。
  • @StephenCleary:您能否通过考虑我的示例来添加您的解决方案?谢谢。
  • @RSH:我不明白你的问题和例子。
猜你喜欢
  • 1970-01-01
  • 2016-01-15
  • 2019-07-20
  • 2021-10-10
  • 2019-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-29
相关资源
最近更新 更多