简体   繁体   English

同步调用不起作用,但是异步调用

[英]Synchronous call not working but asynchronous does

I have a simple method that works in an asynchronous format, but when I try to change it to a synchronous format, it acts like it deadlocks and never returns anything. 我有一个简单的方法,以异步格式工作,但当我尝试将其更改为同步格式时,它就像死锁一样,永远不会返回任何东西。 I know it is more effective to use asynchronous calls but I am curious as to why this is happening. 我知道使用异步调用更有效,但我很好奇为什么会发生这种情况。 Thanks in advance. 提前致谢。

This returns a working result: 这将返回一个工作结果:

public static async Task getCompanyAsync(){
    var client = new getRestClient();
    var response = await companiesApi.GetCompaniesAsync(client);
    var companies = response.GetResultAsync<List<Company>>();
}

This will make the program sit and spin until I kill it: 这会让程序坐下来旋转直到我杀了它:

public static void getCompany(){
    var client = new getRestClient();
    var response = companiesApi.GetCompanies(client);
    var companies = response.GetResult<List<Company>>();
}

Edit: 编辑:

So here is some more detailed code. 所以这里有一些更详细的代码。

    static void Main(string[] args)
    {
        MainAsync(args).Wait();
        Console.ReadLine();
    }
    public static async Task MainAsync(string[] args)
    {
        await getCompanyAsync();
        getCompany();
    }

    private static async Task getCompanyAsync()
    {
        var client = getApiClient();
        var companiesApi = new CompaniesApi(client);
        var response = await companiesApi.GetCompaniesAsync();
        var companyies = await response.GetResultAsync<List<Company>>();
        foreach (var company in companyies)
        {
            Console.WriteLine(company.Name);
        }
    }

    private static void getCompany()
    {
        var client = getApiClient();
        var companiesApi = new CompaniesApi(client);
        var response = companiesApi.GetCompanies();
        var companyies = response.GetResult<List<Company>>();
        foreach (var company in companyies)
        {
            Console.WriteLine(company.Name);
        }

I the application ran as expected when I moved getCompany(); 当我移动getCompany();时,应用程序按预期运行getCompany(); from the MainAsync() method into the Main() method. MainAsync()方法进入Main()方法。

Two points here. 这里有两点。

First, async will often work in unexpected ways in a console application (as compared to a UI application). 首先,异步通常会在控制台应用程序中以意外的方式工作(与UI应用程序相比)。 This is because UIs have a "built in" synchronization contexts (and, obviously, because they don't automatically exit after their "main" method equivalent has completed execution), whereas Console applications don't. 这是因为UI具有“内置”同步上下文(显然,因为它们在“主”方法等效完成执行后不会自动退出),而控制台应用程序则不会。 See this article for directions on how to use a context in a console application to mitigate this. 有关如何在控制台应用程序中使用上下文来缓解此问题的说明,请参阅此文章

Secondly, as pointed out in one of Stephen Cleary's excellent articles on the topic, it's a bad practice to block on async if avoidable as it can lead to exactly the kinds of deadlocks you describe. 其次,正如Stephen Cleary关于该主题的一篇优秀文章所指出的那样,如果可以避免的话,阻止异步是一种不好的做法,因为它可能导致你所描述的各种死锁。 Basically, one way of solving this is to use async "all the way down" - ie use async/await instead of GetResult() in your second sample. 基本上,解决这个问题的一种方法是使用async“一直向下” - 即在第二个示例中使用async / await而不是GetResult()。 This idea is echoed in the Microsoft documentation of best practices for async, which recommend against mixing synchronous and asynchronous code like you do in the second code sample. 这个想法在Microsoft的async最佳实践文档中得到了回应,它建议不要像在第二个代码示例中那样混合同步和异步代码。

In the article I linked to the author explains how a deadlock can occur when you mix synchronous and asynchronous code. 在我与作者链接的文章中解释了混合同步和异步代码时如何发生死锁。 Basically, this can occur when, for example, the async method is waiting for the same context as the GetResults() call is. 基本上,例如,当异步方法等待与GetResults()调用相同的上下文时,就会发生这种情况。 (His article explains it a lot better than me though :) ). (他的文章解释它比我好很多:))。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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