C# 在不等待的情况下调用异步方法 #2

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19786441/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 15:52:49  来源:igfitidea点击:

call async method without await #2

c#asp.netasynchronousasync-awaitc#-5.0

提问by Catalin

I have an async method:

我有一个异步方法:

public async Task<bool> ValidateRequestAsync(string userName, string password)
{
    using (HttpClient client = new HttpClient())
    {
        HttpResponseMessage response = await client.GetAsync(url);
        string stringResponse = await response.Content.ReadAsStringAsync();

        return bool.Parse(stringResponse);
    }
}

I call this method like this:

我这样称呼这个方法:

bool isValid = await ValidateRequestAsync("user1", "pass1");

Can i call the same method from an synchronous method, without using awaitkeyword?

我可以在不使用await关键字的情况下从同步方法调用相同的方法吗?

Ex:

前任:

public bool ValidateRequest(string userName, string password)
{
    return ValidateRequestAsync(userName, password).Result;
}

I think this will cause a deadlock.

我认为这会导致僵局。

EDIT

编辑

Calling the method like above makes the call never end. (The method doesn't reaches the end anymore)

调用上面的方法使调用永不结束。(该方法不再结束)

采纳答案by Kris Vandermotten

If you call an async method from a single threaded execution context, such as a UI thread, and wait for the result synchronously, there is a high probability for deadlock. In your example, that probability is 100%

如果从单线程执行上下文(例如 UI 线程)调用异步方法,并同步等待结果,则死锁的可能性很高。在您的示例中,该概率为 100%

Think about it. What happens when you call

想想看。当你打电话时会发生什么

ValidateRequestAsync(userName, password).Result

You call the method ValidateRequestAsync. In there you call ReadAsStringAsync. The result is that a task will be returned to the UI thread, with a continuation scheduled to continue executing on the UI thread when it becomes available. But of course, it will never become available, because it is waiting (blocked) for the task to finish. But the task can't finish, because it is waiting for the UI thread to become available. Deadlock.

您调用方法 ValidateRequestAsync。在那里你调用 ReadAsStringAsync。结果是一个任务将被返回到 UI 线程,当它变得可用时,一个延续被安排在 UI 线程上继续执行。但当然,它永远不会变得可用,因为它正在等待(阻塞)任务完成。但是任务无法完成,因为它正在等待 UI 线程变为可用。僵局。

There are ways to prevent this deadlock, but they are all a Bad Idea. Just for completeness sake, the following might work:

有一些方法可以防止这种僵局,但它们都是一个坏主意。为了完整起见,以下可能有效:

Task.Run(async () => await ValidateRequestAsync(userName, password)).Result;

This is a bad idea, because you still block your UI thread waiting and doing nothing useful.

这是一个坏主意,因为您仍然会阻止 UI 线程等待并且没有做任何有用的事情。

So what is the solution then? Go async all the way. The original caller on the UI thread is probably some event handler, so make sure that is async.

那么有什么解决办法呢?一路异步。UI 线程上的原始调用者可能是某个事件处理程序,因此请确保它是异步的。

回答by savagepanda

you could use return ValidateRequestAsync(userName, password).GetAwaiter().GetResult();

你可以使用 return ValidateRequestAsync(userName, password).GetAwaiter().GetResult();

回答by IoanaIo

For me it worked using .ConfigureAwait(false) setting in the async call. I have something like

对我来说,它在异步调用中使用 .ConfigureAwait(false) 设置工作。我有类似的东西

return await Entities.SingleOrDefaultAsync(.....).ConfigureAwait(false);