PDA

Просмотр полной версии : C# Многопоточность


thezoke
04.03.2012, 16:17
Вот нормальный урок многопоточности в отличие от этого ([Ссылки могут видеть только зарегистрированные и активированные пользователи])

Если будут вопросы пишите, особы я не тестировал.
Если что-то не так будет пишите.

Для начала добавим элемент.
У меня вот так выглядит.

[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Далее добавить директивы using

using System;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Threading;


Объявим переменные

Thread[] threads; // Обьявляем массив потоков
int i = 0; // позиция
String[] lines = null; // Массив сайтов
Object locks = new Object(); // Object для lock


Добавим такой код на кнопку "старт".
Почти весь код прокомментирован так что я здесь объяснять не буду.


lines = richTextBox1.Lines;
i = 0;
if (lines.Length < 1)
{
MessageBox.Show(this, "Слишком мало сайтов, попробуйте снова!", "Threads Example", MessageBoxButtons.OK, MessageBoxIcon.Stop);
return;
// завершаем если строк меньше 1
}
threads = new Thread[(int)numericUpDown1.Value];
for (int q = 0; q < threads.Length; q++)
{
threads[q] = new Thread(main); // поток будет запускать функцию main
threads[q].Start(); // запускаем
}
new Thread(waitth).Start();


Добавим две функций. Для отправки get запроса и ожидание завершения работы потоков.


private void waitth()
{
for (int q = 0; q < threads.Length; q++)
{
threads[i].Join(); // ожидаем когда потом закончится
}
MessageBox.Show(this, "Работа завершена!", "Threads Example", MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
public string get(string _url, CookieCollection Cooks) // функция для отправки get запроса
{
try
{
[Ссылки могут видеть только зарегистрированные и активированные пользователи] webRequest = ([Ссылки могут видеть только зарегистрированные и активированные пользователи])WebRequest.Create(_url);
webRequest.CookieContainer = new CookieContainer();
webRequest.AllowAutoRedirect = false; // автоматическая переадресация
webRequest.Timeout = 30000; // время ожидания загрузки страницы
webRequest.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.19) Gecko/2010031422 Firefox/3.0.19";

if (Cooks != null)
webRequest.CookieContainer.Add(Cooks);
using ([Ссылки могут видеть только зарегистрированные и активированные пользователи] webResponse = ([Ссылки могут видеть только зарегистрированные и активированные пользователи])webRequest.GetResponse())
{
webResponse.Cookies = webRequest.CookieContainer.GetCookies(webRequest.R equestUri);
if (webResponse.Cookies != null)
Cooks.Add(webResponse.Cookies);
string dataContent = new StreamReader(webResponse.GetResponseStream(), Encoding.GetEncoding(1251)).ReadToEnd();
string end = webResponse.Headers.ToString();
return end + dataContent;
}
}
catch
{
return null; // если была ошибка в загрузке страницы возвращаем null
}
}


На кнопку стоп


for (int q = 0; q < threads.Length; q++)
{
threads[i].Abort(); // прерываем поток
}


Ну и главная функция


private void main()
{
while (true)
{
string url;
lock (locks) // доступ только с одного потока, блокирует доступ с остальных и они в процессе ожидания.
{
if (i > lines.Length - 1) // проверяем не весь ли массив прошли
{
break; // останавливаем поток
}
url = lines[i]; // здесь понятно
i++; // всё равно что i = i +1; или i += 1;
if (!url.Contains("[Ссылки могут видеть только зарегистрированные и активированные пользователи]")) // проверяем, если в линке нету [Ссылки могут видеть только зарегистрированные и активированные пользователи] начинаем цикл заново. url.Contains("[Ссылки могут видеть только зарегистрированные и активированные пользователи]") == False - тоже самое
{
continue; // завершаем потом
}
}
CookieCollection Cooks = new CookieCollection(); // создаём куки менеджер, автоматическии обрабатытает куки
get(url, Cooks); // отправляем get запрос

}
}

sergiktipok
06.03.2012, 03:51
многопоток не работает!доходят только два запроса!

the-boxi
06.03.2012, 15:46
Слишком много всего, можно всё гараздо легче... Ты не пробовал всё в Одну процедуру хотябы засунуть?
new Thread(delegate(){
//код который выполнять потоку
}).Start();

thezoke
06.03.2012, 19:38
Пробовал, так можно ещё и в одну строку написать.

Sinyss
06.03.2012, 20:28
Пробовал, так можно ещё и в одну строку написать.
Любой код можно в 1 строку написать, но нужно ли?

thezoke
07.03.2012, 13:29
А в чем, собственно, разница?
стиль программирования другой

thezoke
07.03.2012, 18:53
Самая частая ошибка при программирование на .net
надо закрывать потоки
webResponse.Close();
так же для всех стреам и тд/problem

Урок был многопоточности, а не отправки get запроса.
Там вроде автоматический закрывает, я точно не помню.

JLeGioH
27.03.2012, 17:17
Открою секрет для тех кто незнает)
threads = new Thread[(int)numericUpDown1.Value];
for (int q = 0; q < threads.Length; q++)
{
threads[q] = new Thread(main); // поток будет запускать функцию main
threads[q].Start(); // запускаем
}
равно на все 100%
єтому:

for (int q = 0; q < (int)numericUpDown1.Value; q++)
{
Thread threads = new Thread(main); // поток будет запускать функцию main
threads.Start(); // запускаем
}
Каждый раз будет создаваться другой поток и первый никуда не денется)
+ Метод МАЙН будет для каждого потока свой индивидуальный(клавное парвильно потокобезопасность сделать)

(Сори за ошЫбки))

the-boxi
27.03.2012, 18:50
/kidding
Ну вообще проше всего вызывать потоки таким методом:
for (int q = 0; q < (int)numericUpDown1.Value; q++)
new Thread(delegate(){Выполняемый код}).Start();

Либо не делегатом и писать код внутри, а ссылаться на процедуру
for (int q = 0; q < (int)numericUpDown1.Value; q++)
new Thread(процедура).Start();

И контролировать поток внутри будет проще всего. То есть сделать его бекграундом, и вызывать обрывание самого же себя после окончания работы./md

Sinyss
27.03.2012, 23:19
/kidding
И контролировать поток внутри будет проще всего. То есть сделать его бекграундом, и вызывать обрывание самого же себя после окончания работы./md
Не всегда потоки могут знать когда им выходить. /problem

the-boxi
27.03.2012, 23:57
Не всегда потоки могут знать когда им выходить. /problem
Ну если не знаешь как работать с потоками, лучше туда не лезть. Но а вообще для этого существует библиотека майкрософта.
Метод Abort - Вызывает исключение ThreadAbortException в вызвавшем его потоке для того, чтобы начать процесс завершения потока. Вызов данного метода обычно завершает поток.
И для этого в конце процедуры пишешь Thread.CurrentThread.Abort();

Sinyss
28.03.2012, 00:55
Ну если не знаешь как работать с потоками, лучше туда не лезть. Но а вообще для этого существует библиотека майкрософта.
Метод Abort - Вызывает исключение ThreadAbortException в вызвавшем его потоке для того, чтобы начать процесс завершения потока. Вызов данного метода обычно завершает поток.
И для этого в конце процедуры пишешь Thread.CurrentThread.Abort();
/kidding
Я умею работать с потоками.
Я имел в виду что потоки могут быть вечными(целенаправленно, например ожидание события)... Или ты можешь послать в поток такую задачу, которая никогда не выполнится(не намеренно), но будет работать правильно... Потому лучше потоки делать с глобальной областью видимости(для класса).