как использовать await и async с richtextbox? - PullRequest
0 голосов
/ 05 июля 2018

Я пытался создать приложение для проверки текущих зрителей на Ebay. я использую следующий код найти Ebay Watcher Count .. он прекрасно работает. затем я использую асинхронный код await для исправления блокировки пользовательского интерфейса ..

но оно получает invalidoperationexception - необработанное исключение.

        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;
    }

У меня мало знаний о await и async ... может кто-нибудь, пожалуйста, исправит эту ошибку?

1 Ответ

0 голосов
/ 06 июля 2018

Попытка получить доступ к элементам управления пользовательского интерфейса из потока, отличного от того, который его создал, приведет к нарушениям доступа между потоками. Поэтому, если целью является выполнение веб-вызовов в фоновом потоке, вам необходимо отделить фоновые задачи от пользовательского интерфейса

.

Ниже приведен рефакторинг исходного кода, который принимает коллекцию идентификаторов и использует HttpClient для выполнения асинхронных веб-вызовов. Все веб-звонки будут выполняться параллельно в отдельных потоках.

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);
}

Итак, теперь в обработчике нажатия кнопок вы запускаете в потоке пользовательского интерфейса, переносите запросы в другие потоки и ждете их завершения, не блокируя поток пользовательского интерфейса. После завершения вы извлекаете возвращенные значения и передаете их по мере необходимости

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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...