teratail header banner
teratail header banner
質問するログイン新規登録

質問編集履歴

3

表示されない状態についての詳細を「発生している問題」と「確認したこと」に追記しました。

2020/05/29 07:37

投稿

heero
heero

スコア8

title CHANGED
File without changes
body CHANGED
@@ -44,6 +44,8 @@
44
44
  ### 発生している問題
45
45
  1枚分のビットマップイメージを受信して表示すること、一定間隔(3秒以上)で受信して表示することには
46
46
  成功しているのですが、受信間隔が短い(3秒未満)場合に2枚目以降のビットマップイメージが表示されません。
47
+ 表示されない状態というのは、1枚目のビットマップイメージが消え、ビットマップイメージ表示領域が
48
+ 白背景の状態です。
47
49
 
48
50
  エラーメッセージの表示やアプリケーションが落ちることはなく、2枚目以降が表示さず動き続けています。
49
51
  上記、「前提・実現したいこと」に記載の処理イメージの6.に記載しているファイル出力は正常に行われており、
@@ -284,6 +286,9 @@
284
286
  (1枚目や一定間隔はできているが)のかと思いネットで情報を探してみたのですが、
285
287
  MVVMでバインディングを介してウィンドウを更新する場合は問題ないという内容が
286
288
  いくつか見つかりました。
289
+ ビットマップイメージを表示するための"Imageタグ"のプロパティにデータがセット
290
+ されていることはデバッグで確認しているのですが、先に表示されていたイメージが
291
+ 消え白背景に更新されてしまいます。
287
292
  そのため、現状何が原因か分からず、手詰まりの状態です。
288
293
 
289
294
  ### 補足情報(FW/ツールのバージョンなど)

2

Viewへのデータ変更を通知するためのViewModelの基底クラス、"ViewModelBase"のソースコードを追加しました。

2020/05/29 07:37

投稿

heero
heero

スコア8

title CHANGED
File without changes
body CHANGED
@@ -73,6 +73,63 @@
73
73
  DataContext = m_viewModel;
74
74
  }
75
75
  ```
76
+ ViewModelBase(ViewModelの基底クラス)
77
+ ```C#
78
+ // ViewModelのプロパティにセットされたデータをViewへ反映する
79
+ public abstract class ViewModelBase : INotifyPropertyChanged, INotifyDataErrorInfo
80
+ {
81
+ ~ViewModelBase()
82
+ {
83
+ ClearResource();
84
+ }
85
+
86
+ private bool _isCrlResource = false;
87
+
88
+ protected virtual void ClearResource()
89
+ {
90
+ if (_isCrlResource) return;
91
+
92
+ if (PropertyChanged != null)
93
+ {
94
+ foreach (var handler in PropertyChanged.GetInvocationList())
95
+ {
96
+ PropertyChanged -= (PropertyChangedEventHandler)handler;
97
+ }
98
+ }
99
+
100
+ PropertyChanged = null;
101
+ _isCrlResource = true;
102
+ }
103
+
104
+ /// <summary>
105
+ /// INotifyPropertyChanged.PropertyChanged の実装。
106
+ /// INotifyPropertyChanged.PropertyChanged implement.
107
+ /// </summary>
108
+ public event PropertyChangedEventHandler PropertyChanged;
109
+
110
+ /// <summary>
111
+ /// INotifyPropertyChanged.PropertyChangedイベントを発生させる。
112
+ /// INotifyPropertyChanged.PropertyChanged event is generated.
113
+ /// </summary>
114
+ protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null)
115
+ {
116
+ if (object.Equals(storage, value)) return false;
117
+
118
+ storage = value;
119
+
120
+ if (PropertyChanged != null)
121
+ {
122
+ PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
123
+ }
124
+ else
125
+ {
126
+ PropertyChanged = null;
127
+ }
128
+
129
+ return true;
130
+ }
131
+ }
132
+ ```
76
133
  WindowViewModel.cs(ViewModel)
77
134
  ```C#
78
135
  // ViewModelBase->INotifyPropertyChanged等を実装した基底クラス

1

USB通信処理を行うC++ DLLの呼び出し部分を追加しました。"USBCommクラス"をModel内でメンバとして使用していましたが間違いでした。

2020/05/28 07:32

投稿

heero
heero

スコア8

title CHANGED
File without changes
body CHANGED
@@ -73,7 +73,6 @@
73
73
  DataContext = m_viewModel;
74
74
  }
75
75
  ```
76
-
77
76
  WindowViewModel.cs(ViewModel)
78
77
  ```C#
79
78
  // ViewModelBase->INotifyPropertyChanged等を実装した基底クラス
@@ -127,44 +126,102 @@
127
126
  bitmapImg = null;
128
127
  }
129
128
 
130
- // ビットマップコントロールにデータをセット
129
+ BitmapImageData = bitmapImg; // ビットマップコントロールにデータをセット
131
- BitmapImageData = bitmapImg;
132
130
  }
133
131
  }
134
132
  ```
135
-
136
133
  WindowModel.cs(Model)
137
134
  ```C#
138
135
  public class WindowModel()
139
136
  {
140
- private USBComm m_usbComm; // USB通信処理クラス
141
137
  private Action<byte[]> m_displayBitmap; // ViewModelのビットマップイメージ表示メソッド
142
138
  private byte[] m_bitmapData; // ビットマップイメージデータ
143
139
 
144
140
  public WindowModel()
145
141
  {
146
- m_usbComm = new USBComm();
147
142
  m_displayBitmap = null;
148
143
  m_bitmapData = null;
149
144
  }
150
145
 
151
146
  public void ReadBitmapImageData()
152
147
  {
153
- m_usbComm.SetDelegateFunc(DisplayBitmapImage);
148
+ USBComm.SetDelegateFunc(DisplayBitmapImage); // イメージデータを取得するためのデリゲート設定
149
+ USBComm.ReadImageData(); // イメージデータ取得
154
150
  }
155
151
 
156
152
  // USB通信処理クラスからビットマップイメージを受け取るデリゲート
157
- private void DisplayBitmapImage(byte[] bitmapData)
153
+ private void DisplayBitmapImage(uint dataSize, bool dataErrFlag)
158
154
  {
155
+ // 受信したデータに異常がない場合のみDLLから取得する
156
+ if (dataErrFlag == false)
157
+ {
158
+ byte[] buff = new byte[dataSize];
159
+ USBComm.GetReceiveData(ref buff);
160
+
159
- m_bitmapData = bitmapData; // 意味ないと思うが念のためメンバにセット
161
+ m_bitmapData = bitmapData; // 意味ないと思うが念のためメンバにセット
162
+ m_displayBitmap(m_bitmapData); // Viewのビットマップイメージ表示メソッド呼び出し
163
+ m_bitmapData = null;
164
+ }
160
165
 
161
- m_displayBitmap(m_bitmapData); // Viewビットマップイメジ表示メソッド呼び出し
166
+ USBComm.ClearReceiveData(); // DLL内タをクリア
167
+ }
168
+ }
169
+ ```
170
+ USBComm.cs(USB通信処理DLLインターフェイス)
171
+ ```C#
172
+ public static class USBComm
173
+ {
174
+ /// <summary>
175
+ /// DLL内で取得したイメージデータのサイズとエラー情報を取得するデリゲート
176
+ /// </summary>
177
+ /// <param name="dataSize">イメージデータサイズ</param>
178
+ /// <param name="errFlag">データエラーフラグ : 0 = Not error / !0 = Error</param>
179
+ public delegate void DelegateDisplayBitmapImage(uint dataSize, byte errFlag);
162
180
 
181
+ static DelegateDisplayBitmapImage m_delegateFunc;
182
+
183
+ // イメージデータ取得用デリゲートメソッドのセット
184
+ [DllImport("USBComm.dll", EntryPoint = "SetDelegateFunc", CallingConvention = CallingConvention.StdCall)]
185
+ private static extern void DllSetDelegateFunc(DelegateDisplayBitmapImage func);
186
+ // イメージデータ受信
187
+ [DllImport("USBComm.dll", EntryPoint = "ReadImageData", CallingConvention = CallingConvention.StdCall)]
188
+ private static extern void DllReadImageData();
189
+ // 受信データ取得
190
+ [DllImport("USBComm.dll", EntryPoint = "GetReceiveData", CallingConvention = CallingConvention.StdCall)]
191
+ private static extern void DllGetReceiveData(IntPtr iPtr);
192
+ // 受信データクリア
193
+ [DllImport("USBComm.dll", EntryPoint = "ClearReceiveData", CallingConvention = CallingConvention.StdCall)]
194
+ private static extern void DllClearReceiveData();
195
+
196
+ public static void SetDelegateFunc(DelegateDisplayBitmapImage func)
197
+ {
163
- m_bitmapData = null;
198
+ m_delegateFunc = func;
199
+ DllSetDelegateFunc(m_delegateFunc );
164
200
  }
201
+
202
+ public static void ReadImageData() => DllReadImageData();
203
+
204
+ public static void GetReceiveData(ref byte[] buff)
205
+ {
206
+ // 取得するデータサイズ分IntPtrのメモリ領域を確保
207
+ IntPtr ptr = Marshal.AllocHGlobal(buff.Length);
208
+ // DLLからデータを取得
209
+ DllGetReceiveData(ptr);
210
+ // DLLから取得したデータをコピー
211
+ Marshal.Copy(iPtr, buff, 0, buff.Length);
212
+ // IntPtrのメモリ解放
213
+ Marshal.FreeHGlobal(ptr);
214
+ }
215
+
216
+ public static void ClearReceiveData() => DllClearReceiveData;
165
217
  }
166
218
  ```
219
+ USBCommクラスで参照しているDLL(USBComm.dll)はC++で実装しています。
220
+ DLLのソースコードは、セキュリティの問題で掲載できません。
221
+ 同じDLLを使用したC++ MFCのツールが存在し、そちらで同じように複数枚のイメージデータを
222
+ 非同期処理で受信→表示することができています。
167
223
 
224
+
168
225
  ### 確認したこと
169
226
  Taskを使用した別スレッドでUIスレッド外からのアクセスのため、表示ができない
170
227
  (1枚目や一定間隔はできているが)のかと思いネットで情報を探してみたのですが、