首页 > 解决方案 > 如何使用富文本框的等待和异步?

问题描述

我试图制作一个应用程序来检查 ebay 当前的观察者。我使用以下代码查找 ebay 观察者计数.. 它很好。然后我使用等待异步代码来修复 UI 阻塞..

但它正在变得无效操作异常是未处理的异常。

        private async void button1_Click(object sender, EventArgs e)
    {
        Task<int> task = new Task<int>(counting);
        task.Start();

        label1.Text = "Please wait";
        await task;

    }

  private int counting()
    {

        string[] idlist = richTextBox1.Text.Split('\n'); // <= getting exception

        // foreach (string id in idlist)
        for (int i = 0; i < Convert.ToInt32(idlist.Length); i++)
        {
            string url = "http://m.ebay.com/itm/" + idlist[i];
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader sr = new StreamReader(response.GetResponseStream());
            // richTextBox2.Text += sr.ReadToEnd();
            string a = sr.ReadToEnd();
            sr.Close();




            string number = String.Empty;
            string pattern = @"(?<=""defaultWatchCount""\s*:\s*)\d+";
            string input = a;

            foreach (Match m in Regex.Matches(input, pattern))
            {
                number = m.Value;

            }
            richTextBox2.Text += number + Environment.NewLine;
        }

        return 0;
    }

我对等待和异步知之甚少......有人可以解决这个错误吗?

标签: c#async-await

解决方案


尝试从与创建它的线程不同的线程访问 UI 控件将导致跨线程访问冲突。因此,如果目标是在后台线程上进行 Web 调用,那么您需要将后台任务与 UI 分开

以下是对原始代码的重构,该代码采用一组 id 并HttpClient用于进行异步 Web 调用。所有的网络调用都将在不同的线程上并行完成。

static Lazy<HttpClient> client = new Lazy<HttpClient>(() => {
    string baseUrl = "http://m.ebay.com/itm/";
    var client = new HttpClient() {
        BaseAddress = new Uri(baseUrl)
    };
    return client;
});

private Task<string[]> GetWatchCountsAsync(string[] idlist) {
    string pattern = @"(?<=""defaultWatchCount""\s*:\s*)\d+";
    var tasks = idlist.Select(async id => {
        var input = await client.Value.GetStringAsync(id.Trim());
        string number = String.Empty;
        foreach (Match m in Regex.Matches(input, pattern)) {
            number += m.Value;
        }
        return number;
    });
    return Task.WhenAll(tasks);
}

所以现在在按钮单击处理程序中,您从 UI 线程开始,将请求卸载到其他线程并等待它们完成,同时不锁定 UI 线程。完成后,您提取返回的值并根据需要传递它们

private async void button1_Click(object sender, EventArgs e) {
    label1.Text = "Please wait..."; //UI Thread
    var idlist = richTextBox1.Text.Split('\n'); //UI Thread
    var numbers = await GetWatchCountsAsync(idlist); //background thread(s) (non-blocking)
    richTextBox2.Text += string.Join(Environment.NewLine, numbers); // Back on UI thread
    label1.Text = "Done"; //UI Thread
}

推荐阅读