我在 Windows CE 应用程序中有此代码:
for (int i = listBoxWork.Items.Count - 1; i > -1; i--)
{
if (listBoxWork.Items[i].ToString().IndexOf(listboxVal) != -1)
{
listBoxWork.Items.RemoveAt(i);
}
}
它因“ System.Collections.ArrayList.ArrayListEnumeratorSimple.MoveNext() 处的无效操作异常而崩溃... ”
我在“常规”Windows 窗体应用程序中尝试了相同的代码,它运行良好。如果这是 Windows CE 无法以这种方式处理的事情,我如何从列表框中删除项目?
更新
这是有效的“VS 2013 代码”(目标框架 == .NET Framework 4.5.1,平台目标 == 任何 CPU)(列表框中的“blaINV”项已删除):
private void button44_Click(object sender, EventArgs e)
{
String listboxVal = "blaINV";
for (int i = listboxWork.Items.Count - 1; i >= 0; --i)
{
if (listboxWork.Items[i].ToString().IndexOf(listboxVal) != -1)
{
listboxWork.Items.RemoveAt(i);
}
}
}
该表单上的 using 语句(这是一个“沙盒”表单,我在其中测试各种事物):
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.OleDb;
using System.DirectoryServices.AccountManagement;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
“VS 2008”代码如下。
首先请注意,该项目的目标框架应该是 .NET 3.5,但“目标框架:”在项目 > 属性 > 应用程序选项卡中显示为灰色;如果我选择项目 > 更改目标平台,“当前平台:”== Windows CE)
但是,如果我转到 Project > Properties > Build 选项卡,Configuration 设置为“Active (Debug)”,Platform 设置为“Active (Any CPU)”,并且 Platform target 设置为“Any CPU”并且是唯一的选项在下拉列表中。
在设备选项卡(项目>属性>设备)上,目标设备设置为“Pocket PC 2003 SE Emulator”,但我并没有真正使用它。当我需要测试时,我只需将 .exe 复制到手持设备。
无论如何,这是代码(失败):
private void UpdateGUIAfterTableSend(String listboxVal)
{
for (int i = listBoxWork.Items.Count - 1; i >= 0; --i)
{
if (listBoxWork.Items[i].ToString().IndexOf(listboxVal) != -1)
{
listBoxWork.Items.RemoveAt(i);
}
}
}
如您所见,除了工作代码中提供了要搜索的“虚假”字符串外,它是相同的。实际的列表框包含一个匹配“listboxVal”的值;然而,它不仅没有被删除,而且出现了上面提到的异常。
以下是非工作表单上唯一的 using 语句:
using System;
using System.Windows.Forms;
namespace HHS
{
using System.Collections.Generic; // R# put this "using" here; like Don Henley in "The Last Resort," I don't know why
更新 2
我将 after-the-namespace using 移动到 above-the-namespace 只是为了看看它是否会产生任何影响。它没有。
更新 3
我在代码中添加了一个 catch 块:
try
{
for (int i = listBoxWork.Items.Count - 1; i >= 0; --i)
{
if (listBoxWork.Items[i].ToString().IndexOf(listboxVal) != -1)
{
listBoxWork.Items.RemoveAt(i);
}
}
}
catch (Exception ex)
{
MessageBox.Show(String.Format(
"Exception in UpdateGUIAfterTableSend(). Message == {0}; InEx == {1}; StackTrace == {2}",
ex.Message, ex.InnerException, ex.StackTrace));
}
......但我没有看到消息框 - 之前的异常显示,并且在它被解雇时,应用程序崩溃 - 即使有一种薄薄的金属“bing”声音,我以前从未从设备中听到过这种声音。
更新 4
好的,为了深入了解这一点,我将 MessageBox.Show() 大量添加到代码中:
private void UpdateGUIAfterTableSend(String listboxVal)
{
try
{
MessageBox.Show("Made it before for loop in UpdateGUIAfterTableSend()");
for (int i = listBoxWork.Items.Count - 1; i >= 0; --i)
{
MessageBox.Show("Made it before if condition in UpdateGUIAfterTableSend()");
if (listBoxWork.Items[i].ToString().IndexOf(listboxVal) != -1)
{
MessageBox.Show("Made it before remove line in UpdateGUIAfterTableSend()");
listBoxWork.Items.RemoveAt(i);
}
}
MessageBox.Show("Made it before listBoxMessages.Items.Add() in
UpdateGUIAfterTableSend()");
listBoxMessages.Items.Add(String.Format("{0} sent at {1}", listboxVal,
DateTime.Now.ToLongTimeString()));
MessageBox.Show("Made it after listBoxMessages.Items.Add() in
UpdateGUIAfterTableSend()");
}
catch (Exception ex)
{
MessageBox.Show(String.Format(
"Exception in UpdateGUIAfterTableSend(). Message == {0}; InEx == {1}; StackTrace
== {2}", ex.Message, ex.InnerException, ex.StackTrace));
}
}
这是这样调用的:
private void menuItemSEND_Inventories_Click(object sender, EventArgs e)
{
SendInventories();
}
private void SendInventories()
{
Cursor curse = Cursor.Current;
Cursor.Current = Cursors.WaitCursor;
try
{
foreach (String tblname in listBoxWork.Items)
{
// Ignore DSD tables
if (tblname.IndexOf("DSD") == 0) continue;
int siteNum = HHSDBUtils.GetSiteNumForTableName(tblname);
String fileName = HHSUtils.GetGeneratedINVFileName(siteNum);
String xmlData = HHSDBUtils.SaveAndGetINVDataAsXMLFromTable(tblname, fileName);
String uri =
String.Format("http:100.200.400.800:1500/api/inventory/sendXML/duckbill/platypus/{0}", fileName);
RESTUtils.SendHTTPRequestNoCredentials(uri, RESTUtils.HttpMethods.POST, xmlData,
"application/xml");
HHSDBUtils.DeleteTableReference(tblname, "INV");
HHSDBUtils.DropSQLiteTable(tblname, siteNum);
UpdateGUIAfterTableSend(tblname);
}
}
finally
{
Cursor.Current = curse;
}
}
所以你可以看到,在 UpdateGUIAfterTableSend() 被调用之后什么都没有发生。这是我在选择 Send > Inventories 并触发这一系列事件之前看到的:
...这就是我在崩溃前看到的内容(listboxitem 删除代码实际上正在工作,我现在可以看到):
在关闭最后一个“成功”的 MessageBox.Show() 时,它会崩溃,如前所述。为什么?!?!?之后就没有其他事情发生了!?!
更新 5
所以我在方法(SendInventories())中添加了一个 catch 块,这实际上是罪魁祸首:
catch (Exception ex)
{
MessageBox.Show(String.Format(
"Exception in SendInventories(); Message == {0}, InEx == {1}, StackTrace == {2}",
ex.Message, ex.InnerException, ex.StackTrace));
}
...我看到了这个:
但是,通过以这种方式捕获异常,应用程序不会崩溃。而且似乎无害——我想要完成的事情已经完成了。所以,虽然肯定对这个例外的来龙去脉感到好奇(没有双关语),但也许我现在就压制/吞下它......
更新 6
因此,如果我将 catch 块更改为:
catch (Exception ex)
{
if (!ex.Message.Contains("InvalidOperationException"))
{
MessageBox.Show(String.Format(
"Exception in SendInventories(); Message == {0}, InEx == {1}, StackTrace == {2}",
ex.Message, ex.InnerException, ex.StackTrace));
}
}
...它工作得很好(我没有看到任何例外,并且两个列表框都按预期更新)。我想我会把它归结为古怪的 Windows CE 世界的变幻莫测。