質問編集履歴
3
表示されない状態についての詳細を「発生している問題」と「確認したこと」に追記しました。
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"のソースコードを追加しました。
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内でメンバとして使用していましたが間違いでした。
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
|
-
|
148
|
+
USBComm.SetDelegateFunc(DisplayBitmapImage); // イメージデータを取得するためのデリゲート設定
|
149
|
+
USBComm.ReadImageData(); // イメージデータ取得
|
154
150
|
}
|
155
151
|
|
156
152
|
// USB通信処理クラスからビットマップイメージを受け取るデリゲート
|
157
|
-
private void DisplayBitmapImage(
|
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
|
-
|
161
|
+
m_bitmapData = bitmapData; // 意味ないと思うが念のためメンバにセット
|
162
|
+
m_displayBitmap(m_bitmapData); // Viewのビットマップイメージ表示メソッド呼び出し
|
163
|
+
m_bitmapData = null;
|
164
|
+
}
|
160
165
|
|
161
|
-
|
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
|
-
|
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枚目や一定間隔はできているが)のかと思いネットで情報を探してみたのですが、
|