C#线程UI被阻塞 | 可能原因为WebRequest.Create?

3

我目前遇到了一个问题,有某些东西阻塞了我的UI线程。我知道它发生在以下函数中:

public async Task<string> function(string username, string password, string handle)
{
    try
    {
        string finalStr;

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://url.com");
        request.CookieContainer = cookie;
        request.AllowAutoRedirect = true;

        var response = await request.GetResponseAsync();

        string str = new StreamReader(response.GetResponseStream(), Encoding.UTF8).ReadToEnd();

        string str2 = this.getToken(str, "_token\" value=\"", "\">", 0);
        string[] textArray1 = new string[] { "postVariables=" + str2 };

        HttpWebRequest httpWebRequest_0 = (HttpWebRequest)WebRequest.Create("https://url.com");
        httpWebRequest_0.CookieContainer = cookie;
        httpWebRequest_0.Method = "POST";
        httpWebRequest_0.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
        httpWebRequest_0.Referer = "https://twitter.com/settings/account";
        httpWebRequest_0.UserAgent = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2";
        httpWebRequest_0.AllowAutoRedirect = true;
        httpWebRequest_0.ContentType = "application/x-www-form-urlencoded";

        byte[] bytes = Encoding.ASCII.GetBytes(string.Concat(textArray1));
        httpWebRequest_0.ContentLength = bytes.Length;

        Stream requestStream = await httpWebRequest_0.GetRequestStreamAsync();
        await requestStream.WriteAsync(bytes, 0, bytes.Length);

        var response2 = await httpWebRequest_0.GetResponseAsync();

        using (StreamReader reader = new StreamReader(response2.GetResponseStream()))
        {
            finalStr = reader.ReadToEnd();
        }

        if (finalStr.Contains(handle))
        {
            return "success";
        }
        else
        {
            requestStream.Close();
            return "error";
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

我认为这是函数的这一部分:

HttpWebRequest httpWebRequest_0 = (HttpWebRequest)WebRequest.Create("https://url.com");

我该如何创建一个async WebRequest.Create? 我是否还做错了其他事情?
感激任何帮助与建议。
3个回答

3

由于WebRequest.Create内部使用了Dns.GetHostByName,这是一个阻塞方法(有时非常缓慢),因此您的代码可能会在该点被阻塞。

一个简单的解决方法是创建一个任务并等待它。

HttpWebRequest request = await Task.Run(()=> WebRequest.Create("https://google.com") as HttpWebRequest);

我认为你复制粘贴了Dns.GetHostByName的错误链接。 - Scott Chamberlain
@ScottChamberlain 这是 Dns.GetHostByName 被引用的地方,而不是它的代码。(也许我应该提到它使用了 gethostname API) - L.B
该链接将我带到了 Internal.cs 中的 WebRequestPrefixElement.Creator 属性。我在 Internal.cs 中除了在 else //!FEATURE_PAL 部分中被禁用的 NclUtilities.GetLocalHost 函数中没有看到任何地方调用 Dns.GetHostByName。 - Scott Chamberlain

1
我建议转换为HttpClient作为未来推荐的客户端。(感谢Erik的提醒)
这需要一些更新才能满足您的需求,但这是开始进行转换的起点。
            using (var client = new HttpClient(new HttpClientHandler
            {
                AllowAutoRedirect = true,
                CookieContainer = new CookieContainer()
            }))
            {
                client.DefaultRequestHeaders.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"));
                client.DefaultRequestHeaders.Referrer = new Uri("https://twitter.com/settings/account");
                client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2");

                // Get
                var result = await client.GetAsync(new Uri(""));
                if (result.IsSuccessStatusCode)
                {
                    var content = await result.Content.ReadAsStringAsync();
                }
                else
                {
                    Console.WriteLine($"{result.StatusCode}: {await result.Content.ReadAsStringAsync()}");
                }

                // Post
                var post = await client.PostAsync("Uri", new StringContent("could be serialized json or you can explore other content options"));
                if (post.IsSuccessStatusCode)
                {
                    var contentStream = await post.Content.ReadAsStreamAsync();
                    var contentString = await post.Content.ReadAsStringAsync();
                }
            }

2
实际上,HttpClient 是新的框架 Http 客户端。 - Erik Philips

-1

你可以通过使用将任何代码转换为异步代码

Task.Run(()=>{
  //any code here...
});

但我认为只要您的输入方法是异步的,那么在调用该方法的代码参照下,该方法下的所有内容都将以异步方式运行。

public async Task<string> function(string username, string password, string handle)

因此,应该在不阻塞用户界面的情况下运行,因为您不需要将所有内容都转换为异步。

请在调用此“函数”时检查是否正在使用async/await。如果您有resharper,通常会告诉您在这种情况下是否缺少async/await,因为没有它,您可能会同步调用方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接