【问题标题】:Async skips execution in the middle of method [duplicate]异步在方法中间跳过执行[重复]
【发布时间】:2021-03-10 04:48:58
【问题描述】:

我正在使用 winforms 从网站上抓取 JSON 数据。

问题是方法没有完成,代码执行在// HttpResponseMessage response = await client.PostAsync($"https://ticks.site/api/numberofticks/geticks?ticks={strTicks}", headers);行停止。

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TicksProgram
{
    public partial class Scanner : Form
    {
        public Scanner()
        {
            InitializeComponent();

            GetJSON().GetAwaiter().GetResult();
        }

        private async Task GetJSON()
        {
            var client = new HttpClient();

            // headers
            var headers = new FormUrlEncodedContent(new[] {
                new KeyValuePair<string, string>("somestring", "somestring"),
               });


            string strTicks = "5";
            // Get the response.
            HttpResponseMessage response = await client.PostAsync(
                $"https://ticks.site/api/numberofticks/geticks?ticks={strTicks}", headers);
            
            // Get the response content.
            HttpContent responseContent = response.Content;
        }
    }
}

没有错误。

我是异步的新手,所以我不确定该怎么做。

【问题讨论】:

  • 警告不是来自此代码。它在别的地方。您需要复制并粘贴整个警告:CS 文件和行号。
  • Main()中,将调用从GetJSON();更改为GetJSON().GetAwaiter().GetResult();或者,将签名从void Main()更改为async Task Main()并调用await GetJSON();
  • 您说您正在使用GetJSON().GetAwaiter().GetResult(); 并且执行停止。这可能是一个僵局。当 IO 绑定操作(Web 请求)释放线程时,它会保存当前上下文。当 IO 绑定操作完成时,它会尝试恢复此上下文(在这种情况下,恢复同一线程上的操作)。为此,它等待线程可用。所以我们正在发生的事情是:.GetAwaiter().GetResult() 正在等待异步操作完成,而异步操作正在等待线程空闲,即等待该行完成。
  • 正确的解决方案可能是将链中的所有内容都设为异步,并使用 async/await 模式。
  • 查看这篇文章:Don't Block on Async Code。它对这种性质的问题提供了非常丰富的信息。

标签: c# async-await dotnet-httpclient


【解决方案1】:

您应该将代码移动到 Form_Load 事件中(您可以通过 Windows 窗体设计器 UI 添加它):

private async void Form_Load(object sender, EventArgs e)
{
    await GetJSON();
}

在 99/100 的情况下,您不应使用 async void,而应使用 async Task。对于 WinForms 事件处理程序,您没有其他选择(您无法更改方法签名),建议使用 async void 进行此操作。

【讨论】:

  • 这不起作用,但我会做更多的研究,因为这似乎是正确的路径。
猜你喜欢
  • 2021-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多