【问题标题】:For loop stops iterating after first item in listboxFor 循环在列表框中的第一项后停止迭代
【发布时间】:2012-01-07 02:18:09
【问题描述】:

我有一个 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]);
        }
    }
}

【问题讨论】:

  • 为什么 listBox8.SetSelected(i, true);那么 listBox8.SelectedIndex = 0;?我的意思是那里还有其他事情发生吗?
  • 你在使用signinmobile方法中的列表选择吗?如果是,那么您可以发布该代码吗?它对我来说看起来不是线程安全的
  • @rfmodulator 我只是放了这两行以确保它选择了第一项,因为没有它们,我的 for 循环就闲置着什么也不做。一旦方法完成,它就会删除选定的项目。
  • @GETah 我编辑并添加了子代码
  • @GETah,当然这不是线程安全的,他必须首先禁用 CheckForIllegalCrossThreadCalls 才能运行。 :)

标签: c# multithreading for-loop iteration


【解决方案1】:

以上答案很好地抓住了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
    }
}

【讨论】:

  • 我正在使用 for 循环而不是 foreach 还是应该切换到 foreach?
  • @user1017524 刚刚编辑了我的代码以使用 for 循环。希望这会有所帮助
  • 不,我仍然需要有关此问题的帮助。谢谢,但我认为您的回答可能对我正在做的事情来说太复杂了:/
【解决方案2】:

下一行总是为每个循环周期选择第一项

listBox8.SelectedIndex = 0;

我相信您完全可以删除这一行,因为前一行 (listBox8.SetSelected(i, true);) 已经进行了选择

编辑:问题已更新

我觉得这里可能会发生异常。在signinmobile 方法调用周围添加try/catch(Exception ex) 块并告诉我们是否处理了任何异常。

顺便说一句,为什么你在另一个线程中运行方法?看起来存在线程同步问题,因此如果列表包含两个以上的项目,则多个线程将运行并删除列表中的项目,然后调用 SetSelected 失败,因为它缓存了索引值 i,该值当前不存在,因为某些线程已被删除项目...所以在单线程中运行全部或在t.Start() 之后执行t.Join(),这样主线程将等到工作线程完成,然后它们继续下一个循环周期。

【讨论】:

  • 我忘了说子在被调用后删除了选定的项目。
  • 如何从列表框中删除项目?请显示代码
  • 我觉得这里可能会发生异常,因为您在 foreach 循环中删除了 Item 。在 signinmobile 方法调用周围添加 try/catch(Exception ex) 块并告诉我们是否处理了任何异常
  • 嘿,抛出的第一个异常是“索引超出数组范围”,然后“对象引用未设置为对象的实例”毫无疑问都是指列表框
  • 我使用的是 for 循环而不是 foreach 循环 ._.
【解决方案3】:

您每次都将SelectedIndex 重置为0,因此它不会继续前进...只需删除该行。

【讨论】:

  • 我忘了说子在被调用后会删除选定的项目。
【解决方案4】:

您再次将选定的索引设置为 0。这是第一项。所以循环的每次迭代都停留在第一项。

【讨论】:

  • 我忘了说子在被调用后会删除选定的项目。
猜你喜欢
  • 1970-01-01
  • 2021-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-05
  • 1970-01-01
  • 2015-10-20
  • 2023-03-11
相关资源
最近更新 更多