c# Помогите правильно реализовать многопоточность
В программу загружаются ссылки из txt и добавляются в очередь. Далее нужно брать ссылку - переходить по ней и парсить значение online И последнее это склеить ссылку и ответ парсера. p/s : учу c# чуть больше недели, сильно не пиннайте )
Многопоточность я реализовал так:
for (int i = 1; i < load.Count; i++)
{
Thread myThread = new Thread(Proccess);
myThread.IsBackground = true;
myThread.Start();
код метода Process
public void Proccess()
{
string url;
while (load.Count > 0)
{
lock (locks)
{
var que = load.Dequeline();
url = que;
}
try
{
hsettings.Reque(url);
Invoke((() =>
{
textBox1.AppendText(url + " | " + hsettings.online + '\r' + '\n');
}));
}
В результате я получаю
https://Myurl1 | 1000 online https://Myurl2 | 1200 online https://Myurl3 | 1000 online
Хотя в Myurl 3 online = 1500, но почему то был взят результат из Myurl1 И каждый запуск выводит разные данные. Я так понимаю, что из за неправильно реализации многопоточности.
Для более точной информации:
Метод Reque:
public void Reque(string line) \\ line берём из очереди
{
using (HttpRequest httpRequest = new()
{
UserAgent = Http.RandomUserAgent(),
AllowAutoRedirect = false,
IgnoreProtocolErrors = true,
UseCookies = false,
EnableEncodingContent = false,
})
try
{
var status = httpRequest.Get($"{line}");
Мне нужно что-бы 10, 100 , 1000 url - без разницы сколько их будет, был получен ответ и из ответа надо достать информацию о кол-ве онлайн пользователей и склеить ссылку с этим кол-вом. Но у меня получается каша. lock пробовал, тоже самое.
Вопрос собственно вот в чём, как из потока сохранить полученную информацию ?
В List ?
Ответы (2 шт):
Для этого лучше использовать Parallel (кто-то может раскритиковать это, ибо принято использовать Task для web части)
private readonly ParallelOptions parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 2 };
private int[] result;
public void Main()
{
string path = @"C:\links.txt";
string[] urls = File.ReadAllLines(path);
result = new int[urls.Length];
Parallel.For(0, urls.Length, parallelOptions, i => ParseUrl(i, urls[i]));
for(int i = 0; i < urls.Length; i++)
Console.WriteLine($"{urls[i]}: {result[i]}");
}
private void ParseUrl(int index, string url)
{
var client = new HttpClient();
int value = int.Parse(/*Какие-то действия, например можно скачать саму страницу и найти в ней значение.*/);
result[i] = value;
}
Узким местом был парсер кол-ва онлайн пользователей, а так-же запись этих данных в textbox.
Решение: обернуть в mutex:
var status = httpRequest.Get($"{url}");
mutexObj.WaitOne();
Respon = status.ToString();
GetUrl = Parse(Respon, "(?<=online_users_id\">).*?(?=</div>)");
textBox1.BeginInvoke(() => { textBox1.AppendText($" {url} | {GetUrl}" + '\r' + '\n'); });
mutexObj.ReleaseMutex();