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 がこの方法で処理できない場合、どうすればListbox から項目を削除できますか?
アップデート
これは、動作する "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)
しかし、[プロジェクト] > [プロパティ] > [ビルド] タブに移動すると、構成が「アクティブ (デバッグ)」に設定され、プラットフォームが「アクティブ (任意の CPU)」に設定され、プラットフォーム ターゲットが「任意の 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
万が一、違いが生じるかどうかを確認するために、名前空間の後を使用して名前空間の上に移動しました。そうではありませんでした。
更新 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));
}
...しかし、メッセージ ボックスが表示されません。前の例外が表示され、それを閉じるとアプリがクラッシュします。これまでデバイスから聞いたことのない薄い金属の「ビン」という音でさえ。
更新 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() が呼び出された後は何も起こりません。これは、[送信] > [インベントリ] を選択し、この一連のイベントを開始する前に表示されるものです。
...そして、これはクラッシュの直前に私が見たものです (listboxitem 削除コードが実際に機能していることがわかりました):
最後に「作成した」MessageBox.Show() を閉じると、前述のようにクラッシュします。どうして?!?!?その後は何もない!?
更新 5
だから私はメソッドにcatchブロックを追加しました(SendInventories())が実際には犯人のようです:
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 の世界の気まぐれのせいにしようと思います。