Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C HTTP请求在控制台应用程序中工作,但在WinForms中不工作_C#_Winforms - Fatal编程技术网

C# C HTTP请求在控制台应用程序中工作,但在WinForms中不工作

C# C HTTP请求在控制台应用程序中工作,但在WinForms中不工作,c#,winforms,C#,Winforms,最初,我创建了一个控制台应用程序来进行一些测试,从服务器获取api调用,并使其功能齐全且工作正常。现在,我想做一个显示,但是来自控制台应用程序的相同代码在winforms应用程序中不起作用。由于一些断点测试,我看到它挂起在这行上: var response = await httpClient.SendAsync(request); 我不明白有什么区别,我已经下载了所有必要的软件包。我想这与使用wait有关。谢谢,伊森 这是排除了私有信息的请求方法代码。我意识到最后有一些不必要的组件,但我只是

最初,我创建了一个控制台应用程序来进行一些测试,从服务器获取api调用,并使其功能齐全且工作正常。现在,我想做一个显示,但是来自控制台应用程序的相同代码在winforms应用程序中不起作用。由于一些断点测试,我看到它挂起在这行上:

var response = await httpClient.SendAsync(request);
我不明白有什么区别,我已经下载了所有必要的软件包。我想这与使用wait有关。谢谢,伊森

这是排除了私有信息的请求方法代码。我意识到最后有一些不必要的组件,但我只是从我最初的测试控制台应用程序复制和粘贴。使用此方法的所有方法(包括main)都是异步的

public async Task<string> APICall(string address)
    {

        string error = "An error was encountered.";
        using (var httpClient = new HttpClient())
        {
            using (var request = new HttpRequestMessage(new HttpMethod("GET"), address))
            {
                request.Headers.TryAddWithoutValidation("Api-Key", "API KEY");
                httpClient.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/hal+json"));

                var response = await httpClient.SendAsync(request);
                if (response.IsSuccessStatusCode)
                {
                    try
                    {
                        Stream res = await response.Content.ReadAsStreamAsync();
                        var serializer = new JsonSerializer();

                        using (var sr = new StreamReader(res))
                        {
                            using (var jsonTextReader = new JsonTextReader(sr))
                            {
                                return await response.Content.ReadAsStringAsync();


                            }

                        }


                    }
                    catch (IOException e)
                    {
                        Console.WriteLine(e);
                    }
                    catch (NullReferenceException e)
                    {
                        Console.WriteLine(e);
                    }
                }

                request.Dispose();
            }
            httpClient.Dispose();
        }
        return error;
    }
这些是调用问题方法的调用方法,从Main到startAsync再到CallAsync,再到APICall,都是有问题的方法

        static async Task Main(string[] args)
    {

                    Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Form1 f = new Form1();
        Caller caller = new Caller();
        string test = await caller.CallAsync();
        foreach (KeyValuePair<string, Server> server in Server.servers)
        {
            f.AddRow(server.Value.name, server.Value.location, server.Value.status, server.Value.ticketStatus);
       }
        Application.Run(f);


    }

public static async Task startAsync()
    {
        Caller caller = new Caller();
        string json = await caller.CallAsync();
        Console.WriteLine(json);
        dynamic name = JsonConvert.DeserializeObject<RootObject>(json);
        List<Location> locs = name._embedded.locations;
        int count = 0;
        foreach (Location loc in locs)
        {
            count++;
            Console.WriteLine(count);
            Server.servers.Add(loc.name, new Server(loc.name, loc.address.city, loc.address.state, loc.id, loc.status, await caller.TicketStatusAsync(loc.id)));

        }
    }
        public async Task<string> CallAsync()
    {
        return await APICall(baseAddress);
    }

最有可能的情况是,在调用堆栈的更上层调用Wait或Result或GetAwaiter.GetResult。换句话说,您的代码是异步同步的。这在控制台应用程序中可以很好地工作——事实上,像这样的一些阻塞是必要的,以便在异步工作完成之前主控制台线程不会退出——但它会在其他上下文中死锁,包括WinForms

它死锁的原因是因为wait默认捕获上下文,并使用该上下文恢复执行异步方法。所以当你等待httpClient时。。。代码运行时,它捕获当前上下文,然后返回一个不完整的任务。然后,堆栈上的调用代码将被阻塞,等待该任务完成

对于WinForms UI线程,该上下文是WinFormsSynchronizationContext,它始终在UI线程上执行代码。因此,当SendAsync完成时,它将继续在UI线程上执行async方法。但是,该UI线程被阻塞,等待任务完成。在UI线程空闲之前,任务无法完成,因此出现死锁


解决此死锁的正确方法是。换句话说,将Wait或Result或GetAwaiter.GetResult替换为Wait。

最有可能的情况是,在调用堆栈的更上层调用Wait或Result或GetAwaiter.GetResult。换句话说,您的代码是异步同步的。这在控制台应用程序中可以很好地工作——事实上,像这样的一些阻塞是必要的,以便在异步工作完成之前主控制台线程不会退出——但它会在其他上下文中死锁,包括WinForms

它死锁的原因是因为wait默认捕获上下文,并使用该上下文恢复执行异步方法。所以当你等待httpClient时。。。代码运行时,它捕获当前上下文,然后返回一个不完整的任务。然后,堆栈上的调用代码将被阻塞,等待该任务完成

对于WinForms UI线程,该上下文是WinFormsSynchronizationContext,它始终在UI线程上执行代码。因此,当SendAsync完成时,它将继续在UI线程上执行async方法。但是,该UI线程被阻塞,等待任务完成。在UI线程空闲之前,任务无法完成,因此出现死锁


解决此死锁的正确方法是。换句话说,将Wait或Result或GetAwaiter.GetResult替换为await。

您在Console应用程序中得到响应了吗?请提供有关代码的更多上下文。控制台应用程序调用此应用程序的方式与WinForms应用程序的方式有什么区别?请求是如何构造的,它包含什么?只是猜测。。。我猜有些方法直接或间接地通过其他方法调用你的方法不是使用Wait,而是使用Wait或Result。这将阻止调用任务,通常是UI任务,因此Wait无法切换回UI任务,从而导致死锁。这不会在控制台中发生,因为它们没有可切换回的同步上下文UI线程。如果没有看到您的方法和调用方法,我无法确定,但您可以使用SendAsync…ConfigureWaitFalse来避免上下文切换。但实际上,async的意思是一路异步,应该避免调用Wait/Result。您在控制台应用程序中得到响应了吗?请提供有关代码的更多上下文。控制台应用程序调用此应用程序的方式与WinForms应用程序的方式有什么区别?请求是如何构造的,它包含什么?只是猜测。。。我猜有些方法直接或间接地通过其他方法调用你的方法不是使用Wait,而是使用Wait或Result。这将阻止调用任务,通常是UI任务,因此Wait无法切换回UI任务,从而导致死锁。这不会发生在控制台中,因为它们没有可切换回的同步上下文UI线程。如果没有看到您的方法和调用方法,我无法确定,但您可以使用SendA
sync…configureWaitFalse以避免上下文切换。但实际上,async是指一路异步,应该避免调用Wait/Result。在我的任何代码中都不会直接调用Wait或Result。使用此方法的所有方法都是异步的。@Eman936:那么请发布一个。@Eman936:一个最小的、可验证的示例需要有所有必要的代码,以便其他人(例如我)可以在本地将其复制/粘贴到项目中并重现问题。@Eman936:我在您的问题中没有看到任何WinForms代码;在我看来,它就像一个控制台应用程序。我建议创建一个新的WinForms项目,然后添加不包含Main的代码。OP不调用应用程序是否重要。运行到异步调用之后?如果我编写一个简短的Winforms应用程序并在调用Application.Run之前检查Synchronization.Current,则结果为null,因此我假设在建立消息循环之前不会设置它。在我的任何代码中都不会直接调用Wait或result。使用此方法的所有方法都是异步的。@Eman936:那么请发布一个。@Eman936:一个最小的、可验证的示例需要有所有必要的代码,以便其他人(例如我)可以在本地将其复制/粘贴到项目中并重现问题。@Eman936:我在您的问题中没有看到任何WinForms代码;在我看来,它就像一个控制台应用程序。我建议创建一个新的WinForms项目,然后添加不包含Main的代码。OP不调用应用程序是否重要。运行到异步调用之后?如果我编写一个简短的Winforms应用程序,并在调用Application.Run之前检查Synchronization.Current,则结果为null,因此我假设在建立消息循环之前不会设置它。