Цикл For перестает повторяться после первого элемента в списке - PullRequest
1 голос
/ 27 ноября 2011

У меня есть цикл for, который я хочу (для каждого элемента в ListBox) выполнить метод.

То, что происходит сейчас, это то, что первый элемент выбирается, метод выполняется, но затем он не выбирает второй элемент, он просто сидит там.

Можешь помочь?

Вот как выглядит мой for цикл:

for(int i = 0; i < listBox8.Items.Count; i++) {
    listBox8.SetSelected(i, true);
    listBox8.SelectedIndex = 0;

    Thread t = new Thread(signinmobile);
    t.Start();
    CheckForIllegalCrossThreadCalls = false;
}

А вот и мой саб:

public void signinmobile()
{
    string yourString = listBox8.SelectedItem.ToString();
    string[] strArray = yourString.Split(':');

    System.Net.ServicePointManager.Expect100Continue = false;
    string postData = "authenticity_token=401538d41ace8f334c3d&username=" + strArray[0] + "&password=" + strArray[1] + "";
    CookieContainer tempCookies = new CookieContainer();
    UTF8Encoding encoding = new UTF8Encoding();
    byte[] byteData = encoding.GetBytes(postData);

    HttpWebRequest postReq = (HttpWebRequest)WebRequest.Create("https://mobile.twitter.com/session");
    postReq.Method = "POST";
    postReq.KeepAlive = true;
    postReq.CookieContainer = tempCookies;
    postReq.ContentType = "application/x-www-form-urlencoded";
    postReq.Referer = "https://mobile.twitter.com/session";
    postReq.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.3) Gecko/20100401 Firefox/4.0 (.NET CLR 3.5.30729)";
    postReq.ContentLength = byteData.Length;

    Stream postreqstream = postReq.GetRequestStream();
    postreqstream.Write(byteData, 0, byteData.Length);
    postreqstream.Close();
    HttpWebResponse postresponse = default(HttpWebResponse);

    postresponse = (HttpWebResponse)postReq.GetResponse();
    tempCookies.Add(postresponse.Cookies);
    StreamReader postreqreader = new StreamReader(postresponse.GetResponseStream());

    string accountstatus = postreqreader.ReadToEnd();

    webBrowser1.DocumentText = accountstatus;

    if (accountstatus.Contains("Sign in information is not correct"))
    {
        listBox9.Items.Add(listBox8.SelectedItem.ToString() + "\r");
        while (listBox8.SelectedItems.Count > 0)
        {
            listBox8.Items.Remove(listBox8.SelectedItems[0]);
        }
    }
    else
    {
        listBox2.Items.Add(listBox8.SelectedItem.ToString() + "\r");

        while (listBox8.SelectedItems.Count > 0)
        {
            listBox8.Items.Remove(listBox8.SelectedItems[0]);
        }
    }
}

Ответы [ 4 ]

1 голос
/ 27 ноября 2011

Вы сбрасываете SelectedIndex на 0 каждый раз, поэтому из этого не следует двигаться вперед ... просто удалите эту строку.

1 голос
/ 27 ноября 2011

В следующей строке всегда выбирается первый элемент для каждого цикла цикла

listBox8.SelectedIndex = 0;

Я считаю, что вы можете вообще удалить эту строку, потому что предыдущая (listBox8.SetSelected(i, true);) уже делает выбор

РЕДАКТИРОВАТЬ: Поскольку вопрос был обновлен

Я чувствую, что здесь может возникнуть исключение.Добавьте try/catch(Exception ex) блок вокруг signinmobile вызова метода и скажите нам, было ли обработано исключение eny.

Кстати, почему вы запускаете метод в другом потоке?Похоже, что существует проблема синхронизации потоков, поэтому, если список содержит более двух элементов, несколько потоков будут запускаться и удалять элементы в списке, а затем вызов SetSelected завершится неудачно, поскольку он кэширует значение индекса i, которое в настоящее время не существует, так как какой-то поток уже удаленitem ... Итак, запустите все в одном потоке или выполните t.Join() после t.Start(), чтобы основной поток ожидал завершения рабочего потока и продолжал следующий цикл цикла.

1 голос
/ 27 ноября 2011

Вы снова устанавливаете выбранный индекс на 0. Это первый элемент. Таким образом, на каждой итерации цикла он остается на первом элементе.

0 голосов
/ 27 ноября 2011

Приведенные выше ответы хорошо уловили проблему listBox8.SelectedIndex = 0;.

Я просто хочу прокомментировать метод signinmobile.

Гуру, исправьте меня, если я ошибаюсь, но если этот метод использует выбор из списка для выполнения некоторой фоновой работы в созданном потоке, тогда все это не будет работать!К тому времени, когда созданный поток вращается и начинает работать с выбранным элементом string yourString = listBox8.SelectedItem.ToString();, родительский поток изменит выбор в for цикле listBox8.SetSelected(i, true);, что может нарушить ранее созданный рабочий поток.Чтобы убедиться, что это потокобезопасно, я бы извлек элемент для работы в цикле for и передал его в виде строки в рабочий поток.Таким образом, вы на 100% уверены, что только один поток обращается к списку и меняет его выбор.

Предлагаемое исправление

for(int i = 0; i < listBox8.Items.Count; i++) {
    Thread t = new Thread(new ParameterizedThreadStart(signinmobile));
    t.Start(listBox8.Items[i].ToString());
}
// Now that you started all thread to work on all items
// You can cleanup the list box safely

public void signinmobile(string parameter) {
    string yourString = parameter; // No need to access the shared list
    //...
    if (accountstatus.Contains("Sign in information is not correct")) {
       listBox9.Items.Add(parameter + "\r");
       // No need to access the shared list to remove the item
    } else  {
       listBox2.Items.Add(parameter + "\r");
       // No need to access the shared list to remove the item
    }
}
...