0

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 の世界の気まぐれのせいにしようと思います。

4

1 に答える 1