[C#] Многопоточность

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by stas1kus, 1 Oct 2014.

  1. stas1kus

    stas1kus New Member

    Joined:
    25 Jun 2012
    Messages:
    33
    Likes Received:
    4
    Reputations:
    0
    Всем доброго времени.
    Столкнулся с проблемой написания многопоточной софтины... вся суть в том, что есть у меня на WinForm загрузка файла в котором в каждой новой строке есть креды на аккаунт (акк,пасс), при загрузке данного списка, для каждого юзера должно создаваться динамически свой WebBrowser для подальших манипуляций данным экземпляром WebBrowser для юзера...

    В общем, создаю N-ное кол-во потоков
    Code:
    for (int i = 0; i < LoadList.userDictionary.Count; i++)
                    {
    usersList.Items.Add(LoadList.userDictionary.ElementAt(i).Key);
                        Thread th = new Thread(() => Main.mainWork(i, LoadList.userDictionary.ElementAt(i).Key, LoadList.userDictionary.ElementAt(i).Value));
                        th.IsBackground = true;
                        th.SetApartmentState(ApartmentState.MTA);
                        th.Start();
                        Thread.Sleep(100);
                    }
    
    которые в свою очередь создают экземпляр браузера, логинятся и данный экзепляр браузера запихиваю в Dictionary, чтоб потом при нажатии на ListBox на форме (какой-то юзер) можно было манипулировать нужным экзепляром браузера

    Code:
    public static void mainWork(int userIndex, string login, string pass)
            {
                WebBrowser webBrowser = new WebBrowser();
                webBrowser.ScriptErrorsSuppressed = true;
                webBrowser.Navigate("http://www.url.ua");
                webBrowser.Document.GetElementById("email-input").SetAttribute("value", login);
                webBrowser.Document.GetElementById("pwd-input").SetAttribute("value", pass);
    
                foreach (HtmlElement el in webBrowser.Document.GetElementsByTagName("button"))
                {
                    if (el.GetAttribute("type").Equals("submit"))
                    {
                        el.InvokeMember("click");
                        break;
                    }
                }
    
                webBrowsersDic.Add(userIndex, webBrowser);
                Thread.Sleep(10);
            }
    
    Когда я делал это в одном потоке - при изменении индекса в ListBox - я мог вызывать нормально свой WebBrowser который находился в Dictionary, но сейчас с потоками оно перестало работать...

    Code:
    private void usersList_SelectedIndexChanged(object sender, EventArgs e)
            {
                Main.selectedAcc(usersList.SelectedIndex);
            }
    
    Подскажите плз как могу организовать "общение" с главного потока по индексу ListBox с нужным браузером (потоком).

    Дополню еще немного, может запутался пока писал этот весь вопрос... на форме есть ListBox с загруженными юзерами (под каждым из них подразумевается экземпляр браузера), при нажатии на конкретную запись (юзера), должна в табличку заноситься разная инфа, которую буду доставать с браузера, + они должны работать параллельно, т.к. там будут бежать разные экшины

    Вот примерно как выглядит форма
    [​IMG]

    PS если я совсем галимо разъяснил, вот можно посмотреть на "проект" :) сейчас он в одном потоке, но нада, как уже выше писал, в нескольких
     
    #1 stas1kus, 1 Oct 2014
    Last edited: 1 Oct 2014
    zyh4n likes this.
  2. #colorblind

    #colorblind Moderator

    Joined:
    31 Jan 2014
    Messages:
    634
    Likes Received:
    246
    Reputations:
    42
    Создаешь массив от 0 до максимального количества потоков
    При создании каждого нового потока, для элемента ListBox, в массив записываешь ThreadID потока.
    Обращаешься к нужному потоку исходя из соответствия ListBox.ItemIndex -> массив[ListBox.ItemIndex]

    p.s.: в сишарпе не разбираюсь, но алгоритм думаю ясен, писал на манер дельфей
     
  3. stas1kus

    stas1kus New Member

    Joined:
    25 Jun 2012
    Messages:
    33
    Likes Received:
    4
    Reputations:
    0
    ок, спс, попробую с этой стороны ;)

    Еще вопрос, когда "умирает" поток? сразу же после создания экземпляра WebBrowser или когда закрываю форму\аппликацию?
     
  4. #colorblind

    #colorblind Moderator

    Joined:
    31 Jan 2014
    Messages:
    634
    Likes Received:
    246
    Reputations:
    42
    Как я понимаю, в шарпе поток умрает либо при принудительном завершении потока через RequestStop, либо при закрытии приложения. А вот если в конце ThreadFunc не будет вызова RequestStop, то будет exception...

    Возможно я полную херню порю, потому что повторюсь, в шарпе совершенно не разбираюсь :D
     
  5. stas1kus

    stas1kus New Member

    Joined:
    25 Jun 2012
    Messages:
    33
    Likes Received:
    4
    Reputations:
    0
    :))) ок... тогда я подожду ответа от другого чувака.
     
  6. M_script

    M_script Members of Antichat

    Joined:
    4 Nov 2004
    Messages:
    2,581
    Likes Received:
    1,317
    Reputations:
    1,557
    Что значит "умирает"?
     
  7. stas1kus

    stas1kus New Member

    Joined:
    25 Jun 2012
    Messages:
    33
    Likes Received:
    4
    Reputations:
    0
    я имею ввиду, могу ли я обращаться к потоку постоянно? или же если он какое-то время находится в бездействии, он закрывается. в моем случае, нужно ли постоянно теребить этот поток чтоб он не закрылся? или он закроется когда я закрою приложение?
     
  8. M_script

    M_script Members of Antichat

    Joined:
    4 Nov 2004
    Messages:
    2,581
    Likes Received:
    1,317
    Reputations:
    1,557
    Если поток завершился, то его больше нет.
    Сделай, чтобы потоки сами брали данные из userDictionary, и завершались, когда переберут все строки.

    upd:
    Что-то типа этого:
    PHP:
    for(int i iThreadNumMainThread->AccList->Count+= MainThread->iThreadCount)
    {
        
    sAcc MainThread->AccList->Strings[i];
    ...
    }
     
    #8 M_script, 2 Oct 2014
    Last edited: 2 Oct 2014
  9. stas1kus

    stas1kus New Member

    Joined:
    25 Jun 2012
    Messages:
    33
    Likes Received:
    4
    Reputations:
    0
    что-то немного не то... :/
     
  10. M_script

    M_script Members of Antichat

    Joined:
    4 Nov 2004
    Messages:
    2,581
    Likes Received:
    1,317
    Reputations:
    1,557
    Неправильно понял. Думал, что нужно всеми аккаунтами зайти и что-то сделать. Напиши ТЗ, чтобы было понятнее, что ты хочешь получить в итоге.
     
  11. stas1kus

    stas1kus New Member

    Joined:
    25 Jun 2012
    Messages:
    33
    Likes Received:
    4
    Reputations:
    0
    да, правильно, нужно чтоб все акки бежали параллельно (т.е. для каждого свой поток в котором свой браузер), и при нажатии на какого-то юзера в листБоксе, выводилась на форме какае-то инфа + были кнопки, для совершения каких-то операций. Но т.к. форма, листБокс с юзерами, кнопки находятся в главном потоке - проблема с передачей данных с главного потока в поток для данного юзера (ИД юзера ну и т.к., но если понять принцип передачи этого ИД в поток с браузером - разберусь и дальше) ну и обратно..

    вот.. как-то так, точного ТЗ нету, софтину пишу для себя..
     
  12. M_script

    M_script Members of Antichat

    Joined:
    4 Nov 2004
    Messages:
    2,581
    Likes Received:
    1,317
    Reputations:
    1,557
    Храни куки юзеров, больше в поток передавать ничего не надо.
    Для каждого действия напиши отдельный метод, который будет принимать куки в качестве параметров. Создал поток, он выполнил нужное действие и завершил работу.