質問編集履歴

2

コードにコメントを追加

2021/09/14 12:28

投稿

tonica
tonica

スコア0

test CHANGED
File without changes
test CHANGED
@@ -214,7 +214,7 @@
214
214
 
215
215
  if (entity == null) return;
216
216
 
217
- await DomainService.HeavyWork(entity);
217
+ await DomainService.HeavyWork(entity); // 他のUseCaseが呼ばれるとエラー
218
218
 
219
219
  DataUpdated?.Invoke(this, EventArgs.Empty);
220
220
 

1

コードの例の追加

2021/09/14 12:28

投稿

tonica
tonica

スコア0

test CHANGED
File without changes
test CHANGED
@@ -39,3 +39,295 @@
39
39
  重い処理(タスク)を管理する仕組みがあるのではないかと思うのですが、
40
40
 
41
41
  そういった仕組みを作って解決するべきでしょうか。
42
+
43
+
44
+
45
+ ####### 追記
46
+
47
+ コードの例です。WPFなのでViewModelでBindingを行っていますが、質問の部分はInteractorの各UseCaseです。
48
+
49
+ 例のためTask.Delayを使っていますが、ProcUseCaseを呼び出した直後にLoadUseCaseを呼び出すとエラーになります。
50
+
51
+ 各UseCaseを排他的に呼び出す処理をInteractorに持たせるか、もしくは非同期な処理を管理するクラスを作るか、
52
+
53
+ このあたりの設計が分からず悩んでいます。
54
+
55
+ 書いていて思ったのですが後者のほうが簡単かもしれません…
56
+
57
+
58
+
59
+ ```C#
60
+
61
+ using System;
62
+
63
+ using System.Threading.Tasks;
64
+
65
+ using System.Windows;
66
+
67
+
68
+
69
+ namespace WpfArchTestApp
70
+
71
+ {
72
+
73
+ internal class Entity
74
+
75
+ {
76
+
77
+ public string Data
78
+
79
+ {
80
+
81
+ get { return disposed ? throw new ObjectDisposedException("Entity") : data; }
82
+
83
+ set { data = value; }
84
+
85
+ }
86
+
87
+ private string data;
88
+
89
+ private bool disposed = false;
90
+
91
+ public void Dispose() { disposed = true; }
92
+
93
+ }
94
+
95
+
96
+
97
+ internal class Repository
98
+
99
+ {
100
+
101
+ public async Task<Entity> Load()
102
+
103
+ {
104
+
105
+ await Task.Delay(1000);
106
+
107
+ return new Entity { Data = "TestStringData" };
108
+
109
+ }
110
+
111
+
112
+
113
+ public async Task Save(Entity _)
114
+
115
+ {
116
+
117
+ await Task.Delay(1000);
118
+
119
+ }
120
+
121
+ }
122
+
123
+
124
+
125
+ internal class DomainService
126
+
127
+ {
128
+
129
+ public static async Task HeavyWork(Entity entity)
130
+
131
+ {
132
+
133
+ for (int i = 0; i < entity.Data.Length; ++i)
134
+
135
+ {
136
+
137
+ for (int j = 0; j < entity.Data.Length; ++j)
138
+
139
+ {
140
+
141
+ if (entity.Data[i] >= entity.Data[j]) continue;
142
+
143
+ char[] charArray = entity.Data.ToCharArray();
144
+
145
+ charArray[j] = entity.Data[i];
146
+
147
+ charArray[i] = entity.Data[j];
148
+
149
+ entity.Data = new string(charArray);
150
+
151
+ await Task.Delay(20);
152
+
153
+ }
154
+
155
+ }
156
+
157
+ }
158
+
159
+ }
160
+
161
+
162
+
163
+ internal class Interactor
164
+
165
+ {
166
+
167
+ public event EventHandler DataUpdated;
168
+
169
+ public string Data { get { return entity == null ? "" : entity.Data; } }
170
+
171
+
172
+
173
+ private readonly Repository repository;
174
+
175
+ private Entity entity;
176
+
177
+
178
+
179
+ public Interactor(Repository repository)
180
+
181
+ {
182
+
183
+ this.repository = repository;
184
+
185
+ }
186
+
187
+
188
+
189
+ public async void LoadUseCase()
190
+
191
+ {
192
+
193
+ if (entity != null)
194
+
195
+ {
196
+
197
+ entity.Dispose();
198
+
199
+ entity = null;
200
+
201
+ }
202
+
203
+ entity = await repository.Load();
204
+
205
+ DataUpdated?.Invoke(this, EventArgs.Empty);
206
+
207
+ }
208
+
209
+
210
+
211
+ public async void ProcUseCase()
212
+
213
+ {
214
+
215
+ if (entity == null) return;
216
+
217
+ await DomainService.HeavyWork(entity);
218
+
219
+ DataUpdated?.Invoke(this, EventArgs.Empty);
220
+
221
+ }
222
+
223
+
224
+
225
+ public async void SaveUseCase()
226
+
227
+ {
228
+
229
+ if (entity == null) return;
230
+
231
+ await repository.Save(entity);
232
+
233
+ entity.Dispose();
234
+
235
+ entity = null;
236
+
237
+ DataUpdated?.Invoke(this, EventArgs.Empty);
238
+
239
+ }
240
+
241
+ }
242
+
243
+
244
+
245
+ internal class MainWindowViewModel : VMCommon.ViewModelBase
246
+
247
+ {
248
+
249
+ public VMCommon.DelegateCommand LoadCommand { get; }
250
+
251
+ public VMCommon.DelegateCommand ProcCommand { get; }
252
+
253
+ public VMCommon.DelegateCommand SaveCommand { get; }
254
+
255
+ public string Data
256
+
257
+ {
258
+
259
+ get { return data; }
260
+
261
+ private set
262
+
263
+ {
264
+
265
+ if (data == value) return;
266
+
267
+ data = value;
268
+
269
+ RaiseProeprtyChanged();
270
+
271
+ }
272
+
273
+ }
274
+
275
+
276
+
277
+ private readonly Interactor interactor;
278
+
279
+ private string data;
280
+
281
+
282
+
283
+ public MainWindowViewModel()
284
+
285
+ {
286
+
287
+ Repository repository = new Repository();
288
+
289
+ interactor = new Interactor(repository);
290
+
291
+ LoadCommand = new VMCommon.DelegateCommand(_ => interactor.LoadUseCase());
292
+
293
+ ProcCommand = new VMCommon.DelegateCommand(_ => interactor.ProcUseCase());
294
+
295
+ SaveCommand = new VMCommon.DelegateCommand(_ => interactor.SaveUseCase());
296
+
297
+ interactor.DataUpdated += Interactor_DataUpdated;
298
+
299
+ }
300
+
301
+
302
+
303
+ private void Interactor_DataUpdated(object sender, EventArgs e)
304
+
305
+ {
306
+
307
+ Data = interactor.Data;
308
+
309
+ }
310
+
311
+ }
312
+
313
+
314
+
315
+ public partial class MainWindow : Window
316
+
317
+ {
318
+
319
+ public MainWindow()
320
+
321
+ {
322
+
323
+ InitializeComponent();
324
+
325
+ DataContext = new MainWindowViewModel();
326
+
327
+ }
328
+
329
+ }
330
+
331
+ }
332
+
333
+ ```