为什么第一次点击按钮事件不起作用

Why first click event of button not working

我有这样的应用程序(net4.7.2):

程序很简单,当用户按下 OK 时,我会向 steam market 发送请求,以获取有关用户输入的商品(商品 Steam 市场 url)到文本框的信息。

但是当我尝试发送请求时,首先单击按钮的事件不起作用:

    private void btnOK_Click(object sender, EventArgs e)
    {
        if (txtItemURL.Text.StartsWith("https://steamcommunity.com/market/listings/730/") == true)
        {
            Helpers.Helper.BuildURL(txtItemURL.Text);

            SteamMarketItem SMI = Helpers.Helper.GetItemDetails();
            lblPrice.Text = SMI.LowestPrice.ToString() + "$";
            pbItemImage.ImageLocation = SMI.ImagePath;

            Helpers.Helper.Kontrollar_BerpaEt();
        }
        else
        {
            Helpers.Helper.Kontrollar_SifirlaYanlisDaxilEdilib();
        }
    }

方法 GetItemDetails():

    public static SteamMarketItem GetItemDetails()
    {
        WinForms.Control.CheckForIllegalCrossThreadCalls = false;

        Task.Run(() =>
        {
            try
            {
                using (HttpClient client = new HttpClient())
                {
                    JavaScriptSerializer serializer = new JavaScriptSerializer();

                    /* Get item info: */
                    var ResultFromEndpoint1 = client.GetAsync(ReadyEndpointURL1).Result;
                    var Json1 = ResultFromEndpoint1.Content.ReadAsStringAsync().Result;
                    dynamic item = serializer.Deserialize<object>(Json1);
                    marketItem.LowestPrice = float.Parse(((string)item["lowest_price"]).Replace("$", "").Replace(".", ","));

                    /* Get item image: */
                    var ResultFromEndpoint2 = client.GetAsync(ReadyEndPointURL2).Result;
                    var Json2 = ResultFromEndpoint2.Content.ReadAsStringAsync().Result;
                    var html = ((dynamic)serializer.Deserialize<object>(Json2))["results_html"];

                    HtmlDocument htmlDoc = new HtmlDocument();
                    htmlDoc.LoadHtml(html);
                    marketItem.ImagePath = htmlDoc.DocumentNode.SelectSingleNode("//img[@class='market_listing_item_img']").Attributes["src"].Value + ".png";

                    Kontrollar_BerpaEt();
                }
            }
            catch
            {
                Kontrollar_SifirlaYanlisDaxilEdilib();
            }
        });

        return marketItem;
    }

Class SteamMarketItem:

public class SteamMarketItem
{
    public string ImagePath { get; set; }
    public float LowestPrice { get; set; }
}

当我使用 Task.Run() 时,第一次点击不起作用,没有 Task.Run() 工作 + 但主 UI 线程在请求​​未完成时停止。

我不知道为什么会这样,我自己找不到问题解决办法,我很乐意得到你的帮助。谢谢。

如果您想使用 async,您需要将事件处理程序更改为 async,以便您可以使用 await,请参阅以下内容:

1. 将您的事件处理程序更改为 async voidasync void 在事件处理程序方法上是可以接受的,您应该尝试使用 async Task在大多数其他情况下代替 async void,因此将您的方法签名更改为以下内容:

   private async void btnOK_Click(object sender, EventArgs e)
   {
        if (txtItemURL.Text.StartsWith("https://steamcommunity.com/market/listings/730/") == true)
        {
            Helpers.Helper.BuildURL(txtItemURL.Text);
            //here we use await to await the task   
            SteamMarketItem SMI = await Helpers.Helper.GetItemDetails();
            lblPrice.Text = SMI.LowestPrice.ToString() + "$";
            pbItemImage.ImageLocation = SMI.ImagePath;

            Helpers.Helper.Kontrollar_BerpaEt();
        }
        else
        {
            Helpers.Helper.Kontrollar_SifirlaYanlisDaxilEdilib();
        }
   }

2. 你应该不需要使用 Task.Run, HttpClient 公开 async 方法,你可以使方法 async,另外,调用 .Result 来阻塞 async 方法通常不是一个好主意,您应该创建封闭方法 async 以便您可以利用 await

   //Change signature to async and return a Task<T>
   public async static Task<SteamMarketItem> GetItemDetails()
   {
       WinForms.Control.CheckForIllegalCrossThreadCalls = false;
       //what is marketItem?? Where is it declared?
       try
       {
           using (HttpClient client = new HttpClient())
           {
               JavaScriptSerializer serializer = new JavaScriptSerializer();

                /* Get item info: */
                var ResultFromEndpoint1 = await client.GetAsync(ReadyEndpointURL1);
                var Json1 = await ResultFromEndpoint1.Content.ReadAsStringAsync();
                dynamic item = serializer.Deserialize<object>(Json1);
                marketItem.LowestPrice = float.Parse(((string)item["lowest_price"]).Replace("$", "").Replace(".", ","));

                /* Get item image: */
                var ResultFromEndpoint2 = await client.GetAsync(ReadyEndPointURL2);
                var Json2 = await ResultFromEndpoint2.Content.ReadAsStringAsync();
                var html = ((dynamic)serializer.Deserialize<object>(Json2))["results_html"];

                HtmlDocument htmlDoc = new HtmlDocument();
                htmlDoc.LoadHtml(html);
                marketItem.ImagePath = htmlDoc.DocumentNode.SelectSingleNode("//img[@class='market_listing_item_img']").Attributes["src"].Value + ".png";

                Kontrollar_BerpaEt();
           }
       }
       catch
       {
            Kontrollar_SifirlaYanlisDaxilEdilib();
       }
       //what is marketItem?? Where is it declared?
       return marketItem;
   }