C# 是否可以停止使用异步并在需要时等待

C# 是否可以停止使用异步并在需要时等待,c#,multithreading,asynchronous,C#,Multithreading,Asynchronous,我正在实现一个使用异步函数的开发人员的代码 例如: public async Task<string> GetDataAsync(string jsonString = "") { string url = $"{this.url}"; using (HttpClient httpClient = new HttpClient()) { using (StringContent body = new StringContent(jsonStr

我正在实现一个使用异步函数的开发人员的代码

例如:

public async Task<string> GetDataAsync(string jsonString = "")
{
    string url = $"{this.url}";

    using (HttpClient httpClient = new HttpClient())
    {
        using (StringContent body = new StringContent(jsonString, Encoding.UTF8, "application/json"))
        {
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", this.accessToken);

            using (HttpResponseMessage response = await httpClient.PostAsync(url, body))
            {
                switch (response.IsSuccessStatusCode)
                {
                    case true:

                        return await response.Content.ReadAsStringAsync();

                    default:

                        throw new Exception($"Error calling url: {url}. HTTP status: {response.StatusCode}");

                }
            }
        }
    }
}
公共异步任务GetDataAsync(字符串jsonString=“”) { 字符串url=$“{this.url}”; 使用(HttpClient HttpClient=new HttpClient()) { 使用(StringContent body=newstringcontent(jsonString,Encoding.UTF8,“application/json”)) { httpClient.DefaultRequestHeaders.Authorization=新的AuthenticationHeaderValue(“承载者”,this.accessToken); 使用(HttpResponseMessage响应=等待httpClient.PostAsync(url,正文)) { 开关(响应。IsSuccessStatusCode) { 大小写正确: return wait response.Content.ReadAsStringAsync(); 违约: 抛出新异常($“调用url时出错:{url}.HTTP状态:{response.StatusCode}”); } } } } } 我不需要,也不想,异步调用任何东西。但问题是异步函数一直在我的函数中冒泡,所以我不能停止使用它,因为HttpClient没有一个
Post()
函数来代替
PostAnync()
,所以我感觉被困在了这个异步框架中

在正常情况下调用异步函数,阻止线程在所有父函数中冒泡,有什么技巧吗


或者说,找到没有异步函数的包的唯一解决方案是什么?

简单的回答是-不,没有通用的方法可以将基于任务的异步函数变成同步函数

问题是您不知道它是如何在内部实现的。比如说,异步函数是使用
async
实现的,并且它(部分)在主线程的上下文中运行。然后,如果调用方代码试图通过阻塞调用阻塞主线程,那么
async
函数也会被阻塞,这会导致死锁

但是,在您的特定情况下,您可以尝试创建一个新任务,从该任务调用
async
函数并获取其结果。有很好的机会,它将工作,但没有保证(如上所述)

代码如下所示:

using (var response = Task.Run(() => httpClient.PostAsync(url, body).Result).Result)
{
    ...
}

简单的回答是-不,没有通用的方法可以将同步函数转换为基于任务的异步函数

问题是您不知道它是如何在内部实现的。比如说,异步函数是使用
async
实现的,并且它(部分)在主线程的上下文中运行。然后,如果调用方代码试图通过阻塞调用阻塞主线程,那么
async
函数也会被阻塞,这会导致死锁

但是,在您的特定情况下,您可以尝试创建一个新任务,从该任务调用
async
函数并获取其结果。有很好的机会,它将工作,但没有保证(如上所述)

代码如下所示:

using (var response = Task.Run(() => httpClient.PostAsync(url, body).Result).Result)
{
    ...
}


Task.Run(GetDataAsync)。结果可能就是您要查找的。它会一直等到异步调用完成。那么,您是否会阻塞异步代码,从而导致死锁?这里真正的问题是:为什么您觉得不需要/不想使用异步?当您想要创建可扩展的应用程序时,您需要这样做
这是一个Web应用程序
只需让异步传播,并在2018年开始使用,也可以使用ConfigureAwait(false),其中可能的异步并不意味着并行。异步执行将有价值的线程池线程从对外部资源的阻塞中释放出来,而不会带来复杂性或性能成本。这意味着同一台IIS机器可以处理更多的并发请求,也就是说,它的可扩展性更高,通常是
Task.Run(GetDataAsync)。结果可能就是您想要的结果。它会一直等到异步调用完成。那么,您是否会阻塞异步代码,从而导致死锁?这里真正的问题是:为什么您觉得不需要/不想使用异步?当您想要创建可扩展的应用程序时,您需要这样做
这是一个Web应用程序
只需让异步传播,并在2018年开始使用,也可以使用ConfigureAwait(false),其中可能的异步并不意味着并行。异步执行将有价值的线程池线程从对外部资源的阻塞中释放出来,而不会带来复杂性或性能成本。这意味着同一台IIS机器可以处理更多的并发请求,也就是说,它的可扩展性更强。这将阻止整个线程池线程。据我所知,任务内部的阻塞具有未定义的行为。还有一件事,这个“响应”实际上是一个任务,因为您没有等待它,所以它甚至不会编译。@FCin从线程池中阻塞一个线程是可以的,我专门为此使用该线程。谢谢你的第二条评论-我更正了代码。如果你多次调用这个方法是不好的。每次它都会安排另一个线程池线程,导致它完全阻塞线程池并使应用程序暂时无响应。同时调用
.Result
而不调用
configurewait
将使asp.net应用程序死锁,因为任务将等待SynchronizationContext(UI)线程释放,但它永远不会空闲,因为它将等待任务完成。@FCin我的代码一次不会使用线程池中的多个线程。我不明白你说的“阻止线程池”是什么意思。这将阻止整个线程池线程。据我所知,任务内部的阻塞具有未定义的行为。还有一件事,这个“响应”实际上是一个任务,因为您没有等待它,所以它甚至不会编译。@FCin从线程池中阻塞一个线程是可以的,我专门为此使用该线程。谢谢你的第二条评论-我纠正了错误