Я хочу запускать несколько потоков одновременно (максимум 5 потоков, например), и когда один из них заканчивается, новый начинается с разных данных. (один заканчивается, один новый старт, два окончания, два новых начала ...)
Основной для цикла в основной форме, но выполняется из другого потока, чтобы не блокировать пользовательский интерфейс.Семафор, похоже, не работает с несколькими потоками
Когда я запускаю его, программа добавляет 5 элементов управления веб-браузером (как визуальный прогресс), а когда страница загружается, она удаляет загруженные.
Проблема заключается в том, что в форму не добавляются элементы управления.
Возможно, семафор не выпущен должным образом, чтобы разрешить запуск новых, или я пропустил что-то еще?
И если я закрою программу, она не выйдет, я думаю, что она блокируется на WaitHandle.WaitOne, потому что еще предстоит сделать больше заданий.
Я удалил некоторые ненужные данные для большей ясности кода.
Semaphore pool = new Semaphore(5, 5);
Scraper[] scraper = new Scraper[5];
Gecko.GeckoWebBrowser wb = null;
int j = 0;
for (int i = 0; i < arrScrapeboxItems.Count; i++)
{
pool.WaitOne();
bool pustiMe = true;
while (pustiMe)
{
if (scraper[j] == null) scraper[j] = new Scraper();
if (scraper[j].tred == null)
{
ScrapeBoxItems sbi = (ScrapeBoxItems)arrScrapeboxItems[i];
doneEvents.Add(new ManualResetEvent(false)); // this is for WaitHandle.WaitAll after the for loop is done all the items
wb = new Gecko.GeckoWebBrowser();
PoolObjects po = new PoolObjects();
po.link = sbi.link;
// etc...
scraper[j].ThreadsCompleted += new Scraper.ThreadsHandler(frmMain_NextThreadItemsCompleted);
scraper[j].tred = new Thread(new ParameterizedThreadStart(scraper[j].Scrape));
scraper[j].tred.Start(po);
pustiMe = false;
if (j == maxThreads - 1)
j = 0;
else
j++;
break;
}
else if (scraper[j].tred.IsAlive) // if the thread is finished, make room for new thread
{
scraper[j] = null;
}
if (pustiMe) Thread.Sleep(1000);
}
}
// event from Scraper class
void frmMain_ThreadsCompleted()
{
pool.Release();
}
А класс вид скребок, как:
public void Scrape(object o)
{
po = (PoolObjects)o;
// do stuff with po
po.form.Invoke((MethodInvoker)delegate
{
po.form.Controls.Add(po.wb);
po.wb.DocumentCompleted += new EventHandler<Gecko.Events.GeckoDocumentCompletedEventArgs>(wb_DocumentCompleted);
po.wb.Navigate(po.link);
});
}
void wb_DocumentCompleted(object sender, Gecko.Events.GeckoDocumentCompletedEventArgs e)
{
var br = sender as Gecko.GeckoWebBrowser;
if (br.Url == e.Uri)
{
form.Controls.Remove(po.wb);
ThreadsCompleted();
manualReset.Set();
}
}
Похоже на две возможные проблемы. Вы используете один и тот же веб-браузер для каждого потока вместо создания нового и добавляете его в форму. Во-вторых, вы не указываете координаты и размер веб-браузера в форме. Они, вероятно, находятся на вершине друг друга. – TyCobb
@TyCobb Я переместил объект браузера внутри цикла, но безрезультатно, та же проблема. У меня есть код для управления браузером по горизонтали, поэтому он не на вершине друг друга. Здесь есть что-то еще. Спасибо за ответ. – lopkiju