Попытка получить доступ к элементам управления пользовательского интерфейса из потока, отличного от того, который его создал, приведет к нарушениям доступа между потоками. Поэтому, если целью является выполнение веб-вызовов в фоновом потоке, вам необходимо отделить фоновые задачи от пользовательского интерфейса
.
Ниже приведен рефакторинг исходного кода, который принимает коллекцию идентификаторов и использует 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
}