質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

1回答

4965閲覧

C# List参照時のSystem.NullReferenceException発生について

Taffy

総合スコア33

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2020/02/21 05:03

編集2020/02/21 06:39

C#を使用して開発しています。
開発環境は、Visual Studio Express 2017 for Windows Desktopを使用しています。

Listに格納したデータをFormクラスで参照する際に、System.NullReferenceExceptionが発生し
対処方法がわからず困っています。
イメージ説明

  • Listの状態

以下のように作りました。このListはForm側とControl側、複数のスレッドで使われます。

C#

1class CSData 2{ 3public List<CData> lstData = new List<CData>(); 4 5・・・ 6

CDataは以下のように作りました。

C#

1public struct CData 2{ 3 public string m_strName; 4 public ushort m_wData; 5 public bool[] m_bData; 6}
  • 当方で試したこと

CDataが、struct型で、初期化を行っていないことが原因ではないかと思い
classに変えました。
さらに、コンストラクタを追加し、確実に初期化を行うようにしました。

C#

1public class CData 2{ 3 public string m_strName; 4 public ushort m_wData; 5 public bool[] m_bData; 6 7 public CData() 8 { 9 m_strName= ""; 10 m_wData = 0; 11 m_bData = new bool[8]; 12 for (int i = 0; i < m_bData.Length; i++) 13 { 14 m_bData[i] = false; 15 } 16 } 17}

参照時は、lockを使っていますので
lock中に他のスレッド(Control)によってListの内容を変更されることがないものと考えています。

また、例外が発生したコードは以下の通りです。

C#

1if ((m_cls.lstData != null) 2 && (m_cls.lstData.Count> nRow) 3 && (m_cls.lstData[nRow].m_bData != null)) 4{ 5 ・・・ 6

このような例外が発生する原因、疑わしいところと、対策についてご教示いただけますでしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YAmaGNZ

2020/02/21 05:14

lstDataとlstcDataがありますが、記載ミスですか?
workaholist

2020/02/21 05:17

どこでCDataのインスタンスを生成してますか?
Taffy

2020/02/21 05:19

すみません。誤記がありましたので修正しました。 CDataのインスタンスは、lstData追加時に作成しています。 Formではなく、Control側のスレッドで作成しています。 CData cData = new CData(); cData.m_strName = "xxx"; … m_cls.lstData.Add(cData); といったイメージです。
dodox86

2020/02/21 05:22

lockを使っているから大丈夫とのことですが、その使い方に間違いが無いことは保証できますか。例えばlstcData[nRow].m_bData != null)を評価する寸前、別のスレッドでlstcDataの要素を削除していたらNGです。そもそもlockって、何のクラスオブジェクトなのか回答者には分かりませんし。 コード全体を見ないと判断つかないのではないでしょうか。
Taffy

2020/02/21 05:24

CDataを内包するクラスCSDataがあり、 CSDataの中でListを定義しています。 CSDataはシングルトンの構成にしてあるため どのスレッドからでも呼び出せるようにしてあります。 CSData m_cls = new CSData.GetInstance();
Zuishin

2020/02/21 05:25

エラーメッセージを見ると、lstcData[nRow] が null のようです。
dodox86

2020/02/21 05:33

> CSData m_cls = new CSData.GetInstance(); 既に生成済みのシングルトン用のオブジェクトを返すであろうstaticメソッドのGetInstance()の返り値に対してnew するとは?この時点で私には分からないので、回答は難しそうです。
hihijiji

2020/02/21 06:21

貴方に原因がわからないなら貴方が原因だと思ってないところに原因があるのが普通です。 貴方が原因だと思っているところを抜粋しても何も解決しません。 現象が発生する最小コードを提示してください。
YAmaGNZ

2020/02/21 06:39

CSDataでlstDataはどのように定義しているのですか? ただ Class CSData { public List<CData> lstData = new List<CData>(); } としているのであれば提示された読み込むロジック部分でロックがかかっていないのではないですか?
Taffy

2020/02/21 06:41

排他制御が正しく行われていないのではないか?という切り口で再度調べたところ 排他制御が正しく行われていなかったことが原因とわかりました。 また、シングルトンのオブジェクトを受け取る処理は誤記です。 以下が正です。 CSData m_cls = CSData.GetInstance();
guest

回答1

0

自己解決

排他制御が原因で、削除された項目にForm側からアクセスしているとわかりました。
ロック用に使われていたオブジェクトが
各クラスで宣言されたものを使用していたため、
すべてのクラスで共通で使用できるオブジェクトに変更し
ロック処理が異なるスレッドでも行われるようにしました。

<<補足>>
リストは、以下のようなイメージで作成していました。

C#

1class CSData 2{ 3 public class CData 4 { 5 public string m_strName; 6 public ushort m_wData; 7 public bool[] m_bData; 8 9 public CData() 10 { 11 m_strName= ""; 12 m_wData = 0; 13 m_bData = new bool[8]; 14 for (int i = 0; i < m_bData.Length; i++) 15 { 16 m_bData[i] = false; 17 } 18 } 19 } 20 public List<CData> lstData = new List<CData>(); 21 22・・・ 23

CSDataクラスはシングルトンで、複数のクラスからアクセス可能としています。

C#

1CSData m_cls = CSData.GetInstance(); // ※補足回答に書いたnewは間違い 2 3if ((m_cls.lstData != null) 4 && (m_cls.lstData.Count> nRow) 5 && (m_cls.lstData[nRow].m_bData != null)) 6{ 7

今回、CSDataクラスに排他制御用オブジェクトを追加し、
lstDataを使うオブジェクトはすべてCSDataクラスの排他制御オブジェクトを使うように修正しました。

C#

1class CSData 2{ 3 public Object lockObj = new Object(); 4 public class CData 5 { 6・・・ 7

C#

1lock (m_cls.lockObject) 2{ 3・・・ 4 if ((m_cls.lstData != null) 5 && (m_cls.lstData.Count> nRow) 6 && (m_cls.lstData[nRow].m_bData != null)) 7 {

投稿2020/02/21 06:36

Taffy

総合スコア33

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問