質問編集履歴

5

2019/09/18 22:03

投稿

kaito_19950605
kaito_19950605

スコア4

test CHANGED
File without changes
test CHANGED
@@ -36,6 +36,14 @@
36
36
 
37
37
 
38
38
 
39
+ 下記のソースコードのようにすると、以下のようになってしまいます。
40
+
41
+ 1. 1つ目のプロセスでイベント登録(OnCallback)。
42
+
43
+ 2. 2つ目のプロセスでInvokeしようとすると、OnCallbackがnullになっていてInvokeされない。
44
+
45
+
46
+
39
47
  ### 該当のソースコード
40
48
 
41
49
 

4

「前提・実現したいこと」に追記しました。

2019/09/18 22:03

投稿

kaito_19950605
kaito_19950605

スコア4

test CHANGED
File without changes
test CHANGED
@@ -16,6 +16,14 @@
16
16
 
17
17
 
18
18
 
19
+ ClientとServiceの双方向通信のサンプルはネット上にたくさん転がっていますが、
20
+
21
+ あるClientがイベントを叩くと、もう一方のClientにイベント通知がされる、
22
+
23
+ というパターンが見つかりませんでした。
24
+
25
+
26
+
19
27
  参考としてサイトをご紹介頂ける場合は、英語のサイトでも構いません。
20
28
 
21
29
 

3

イメージ画像を追加しました。

2019/09/18 12:08

投稿

kaito_19950605
kaito_19950605

スコア4

test CHANGED
File without changes
test CHANGED
@@ -10,6 +10,10 @@
10
10
 
11
11
  WCFを利用したプロセス間のイベント通知によるデータ転送の実現方法を教えて頂きたいです。
12
12
 
13
+ やりたいことのイメージとして、以下の画像を参考にして下さい。
14
+
15
+ ![イメージ説明](b1fcaceee54f9d08c89526427762a332.png)
16
+
13
17
 
14
18
 
15
19
  参考としてサイトをご紹介頂ける場合は、英語のサイトでも構いません。

2

コールバックインターフェースの実装方法を変更しました。

2019/09/18 12:05

投稿

kaito_19950605
kaito_19950605

スコア4

test CHANGED
File without changes
test CHANGED
@@ -8,11 +8,11 @@
8
8
 
9
9
  プロセス間でイベント通知を行い、データを転送したいのですが、双方向通信にしてもイベントが飛びません。
10
10
 
11
-
12
-
13
11
  WCFを利用したプロセス間のイベント通知によるデータ転送の実現方法を教えて頂きたいです。
14
12
 
13
+
14
+
15
- 英語のサイトでも構いません。
15
+ 参考としてサイトをご紹介頂ける場合は、英語のサイトでも構いません。
16
16
 
17
17
 
18
18
 
@@ -36,37 +36,45 @@
36
36
 
37
37
  {
38
38
 
39
- // メモ: [リファクター] メニューの [名前の変更] コマンドを使用すると、コードと config ファイルの両方で同時にインターフェイス名 "IService1" を変更できます。
40
-
41
39
  [ServiceContract(CallbackContract = typeof(IGetResponseCallback))]
42
40
 
43
41
  public interface IDataTransferService
44
42
 
45
43
  {
46
44
 
47
- // TODO: ここにサービス操作を追加します。
48
-
49
-
50
-
51
45
  [OperationContract(IsOneWay = true)]
52
46
 
53
47
  void Register(byte[] data);
54
48
 
49
+
50
+
55
51
  [OperationContract(IsOneWay = true)]
56
52
 
57
53
  void Clear();
58
54
 
55
+
56
+
59
57
  [OperationContract]
60
58
 
61
59
  byte[] GetResponse(UInt32 id, byte[] request);
62
60
 
61
+
62
+
63
+ /// <summary>
64
+
65
+ /// コールバック用
66
+
67
+ /// </summary>
68
+
69
+ /// <param name="id"></param>
70
+
71
+ /// <param name="message"></param>
72
+
73
+ [OperationContract(IsOneWay = true)]
74
+
75
+ void Send(UInt32 id, byte[] message);
76
+
63
- }
77
+ }
64
-
65
-
66
-
67
- // サービス操作に複合型を追加するには、以下のサンプルに示すようにデータ コントラクトを使用します。
68
-
69
- // プロジェクトに XSD ファイルを追加できます。プロジェクトのビルド後、そこで定義されたデータ型を、名前空間 "DataTransferWCFService.ContractType" で直接使用できます。
70
78
 
71
79
  }
72
80
 
@@ -106,490 +114,524 @@
106
114
 
107
115
  {
108
116
 
109
- // メモ: [リファクター] メニューの [名前の変更] コマンドを使用すると、コードと config ファイルの両方で同時にクラス名 "Service1" を変更できます。
110
-
111
- public class DataTransferService : IDataTransferService, IGetResponseCallback
117
+ public class DataTransferService : IDataTransferService
112
118
 
113
119
  {
114
120
 
115
121
  private static List<byte[]> dataList = new List<byte[]>();
116
122
 
123
+
124
+
125
+ public void Clear()
126
+
127
+ {
128
+
129
+ dataList.Clear();
130
+
131
+ }
132
+
133
+
134
+
135
+ public byte[] GetResponse(uint id, byte[] request)
136
+
137
+ {
138
+
139
+
140
+
141
+ byte[] response = dataList.ElementAt((int)id)
142
+
143
+ .Concat(request)
144
+
145
+ .ToArray();
146
+
147
+
148
+
149
+ return response;
150
+
151
+ }
152
+
153
+
154
+
155
+ public void Register(byte[] data)
156
+
157
+ {
158
+
159
+ dataList.Add(data);
160
+
161
+ }
162
+
163
+
164
+
165
+ /// <summary>
166
+
167
+ /// コールバック用
168
+
169
+ /// </summary>
170
+
171
+ /// <param name="id"></param>
172
+
173
+ /// <param name="request"></param>
174
+
175
+ public void Send(uint id, byte[] message)
176
+
177
+ {
178
+
179
+ IGetResponseCallback callback = OperationContext.Current.GetCallbackChannel<IGetResponseCallback>();
180
+
181
+
182
+
183
+ callback.GetResponseCallback(id, message);
184
+
185
+ }
186
+
187
+ }
188
+
189
+ }
190
+
191
+ ```
192
+
193
+
194
+
195
+ サービスの開始周り(DataTransfer.cs)
196
+
197
+ ```C#
198
+
199
+ namespace DataTransfer
200
+
201
+ {
202
+
203
+ public class DataTransfer
204
+
205
+ {
206
+
207
+ public _DataTransfer instance = _DataTransfer.Instance;
208
+
209
+
210
+
211
+ /// <summary>
212
+
213
+ /// サービスの開始とチャンネルの実体化
214
+
215
+ /// </summary>
216
+
217
+ public void PreStart()
218
+
219
+ {
220
+
221
+ this.instance.Start();
222
+
223
+ this.instance.Create();
224
+
225
+ }
226
+
227
+
228
+
229
+ /// <summary>
230
+
231
+ /// チャンネルの実体化
232
+
233
+ /// </summary>
234
+
235
+ public void Create()
236
+
237
+ {
238
+
239
+ this.instance.Create();
240
+
241
+ }
242
+
243
+
244
+
245
+ public void Register(byte[] data)
246
+
247
+ {
248
+
249
+ this.instance.Register(data);
250
+
251
+ }
252
+
253
+
254
+
255
+ public void Clear()
256
+
257
+ {
258
+
259
+ this.instance.Clear();
260
+
261
+ }
262
+
263
+
264
+
265
+ public byte[] GetResponse(UInt32 id, byte[] request)
266
+
267
+ {
268
+
269
+ return this.instance.GetResponse(id, request);
270
+
271
+ }
272
+
273
+ }
274
+
275
+
276
+
277
+ public class _DataTransfer : IGetResponseCallback
278
+
279
+ {
280
+
281
+ private static string PIPE_NAME = @"net.pipe://sample";
282
+
283
+ public ServiceHost host;
284
+
285
+ public IDataTransferService proxy;
286
+
287
+ public DuplexChannelFactory<IDataTransferService> factory;
288
+
117
289
  public delegate void CallbackEventHandler(object sender, CommunicationEventArgs args);
118
290
 
119
291
  public event CallbackEventHandler OnCallback;
120
292
 
293
+ //シングルトンパターン
294
+
295
+ private static _DataTransfer instance = new _DataTransfer();
296
+
297
+ public static _DataTransfer Instance
298
+
299
+ {
300
+
301
+ get
302
+
303
+ {
304
+
305
+ return instance;
306
+
307
+ }
308
+
309
+ }
310
+
311
+
312
+
313
+ private _DataTransfer()
314
+
315
+ {
316
+
317
+
318
+
319
+ }
320
+
321
+
322
+
323
+ /// <summary>
324
+
325
+ /// サービスを開始
326
+
327
+ /// </summary>
328
+
329
+ public void Start()
330
+
331
+ {
332
+
333
+ Instance.host = new ServiceHost(typeof(IDataTransferService), new Uri(PIPE_NAME));
334
+
335
+
336
+
337
+ Instance.host.AddServiceEndpoint(typeof(IDataTransferService), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
338
+
339
+ {
340
+
341
+ ReceiveTimeout = TimeSpan.MaxValue
342
+
343
+ }, string.Empty);
344
+
345
+
346
+
347
+ try
348
+
349
+ {
350
+
351
+ host.Open();
352
+
353
+ }
354
+
355
+ catch (Exception ex)
356
+
357
+ {
358
+
359
+ Debug.WriteLine(ex.Message);
360
+
361
+ }
362
+
363
+ }
364
+
365
+
366
+
367
+ /// <summary>
368
+
369
+ /// チャンネルの実体化
370
+
371
+ /// </summary>
372
+
373
+ public void Create()
374
+
375
+ {
376
+
377
+ Instance.factory = new DuplexChannelFactory<IDataTransferService>(new InstanceContext(Instance), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
378
+
379
+ {
380
+
381
+ MaxReceivedMessageSize = Int32.MaxValue
382
+
383
+ }, PIPE_NAME);
384
+
385
+ Instance.proxy = Instance.factory.CreateChannel();
386
+
387
+ }
388
+
121
389
 
122
390
 
123
391
  public void Clear()
124
392
 
125
393
  {
126
394
 
127
- dataList.Clear();
128
-
129
- }
130
-
131
-
132
-
133
- public byte[] GetResponse(uint id, byte[] request)
134
-
135
- {
136
-
137
- IGetResponseCallback callback = OperationContext.Current.GetCallbackChannel<IGetResponseCallback>();
138
-
139
- byte[] response = dataList.ElementAt((int)id)
140
-
141
- .Concat(request)
142
-
143
- .ToArray();
144
-
145
-
146
-
147
- callback.GetResponseCallback(id, response);
148
-
149
-
150
-
151
- return response;
152
-
153
- }
154
-
155
-
395
+ try
396
+
397
+ {
398
+
399
+ Instance.proxy.Clear();
400
+
401
+ }
402
+
403
+ catch(Exception ex)
404
+
405
+ {
406
+
407
+ Debug.WriteLine(ex.Message);
408
+
409
+ }
410
+
411
+ }
412
+
413
+
414
+
415
+ public void Register(byte[] data)
416
+
417
+ {
418
+
419
+ try
420
+
421
+ {
422
+
423
+ Instance.proxy.Register(data);
424
+
425
+ }
426
+
427
+ catch(Exception ex)
428
+
429
+ {
430
+
431
+ Debug.WriteLine(ex.Message);
432
+
433
+ }
434
+
435
+ }
436
+
437
+
438
+
439
+ public byte[] GetResponse(UInt32 id, byte[] request)
440
+
441
+ {
442
+
443
+ try
444
+
445
+ {
446
+
447
+ Instance.proxy.Send(id, request);
448
+
449
+
450
+
451
+ byte[] response = Instance.proxy.GetResponse(id, request);
452
+
453
+
454
+
455
+ Instance.proxy.Send(id, response);
456
+
457
+
458
+
459
+ return response;
460
+
461
+ }
462
+
463
+ catch(Exception ex)
464
+
465
+ {
466
+
467
+ Debug.WriteLine(ex.Message);
468
+
469
+
470
+
471
+ return null;
472
+
473
+ }
474
+
475
+ }
476
+
477
+
478
+
479
+ /// <summary>
480
+
481
+ /// コールバックメソッドの実装
482
+
483
+ /// </summary>
484
+
485
+ /// <param name="id"></param>
486
+
487
+ /// <param name="message"></param>
156
488
 
157
489
  public void GetResponseCallback(uint id, byte[] message)
158
490
 
159
491
  {
160
492
 
493
+ Instance.OnCallback?.Invoke(this, new CommunicationEventArgs(id, message));
494
+
495
+ }
496
+
497
+ }
498
+
499
+ }
500
+
501
+ ```
502
+
503
+
504
+
505
+ 本体(Program.cs)
506
+
507
+ ```C#
508
+
509
+ namespace WCFIPC
510
+
511
+ {
512
+
513
+ class Program
514
+
515
+ {
516
+
517
+ static void Main(string[] args)
518
+
519
+ {
520
+
521
+ //1つ目のプロセスでは
522
+
523
+ Transfer transfer = new Transfer();
524
+
525
+ transfer.Register(new byte[] { 0x12, 0x34, 0x56 });
526
+
527
+
528
+
529
+ //2つ目のプロセスでは
530
+
531
+ DataTransfer.DataTransfer dataTransfer = new DataTransfer.DataTransfer();
532
+
533
+ dataTransfer.Create();
534
+
535
+ var response = dataTransfer.GetResponse(0xFF, new byte[] { 0x78, 0x90 });
536
+
537
+ }
538
+
539
+ }
540
+
541
+
542
+
543
+ class Transfer
544
+
545
+ {
546
+
547
+ public DataTransfer.DataTransfer service = new DataTransfer.DataTransfer();
548
+
549
+
550
+
551
+ public void Register(byte[] data)
552
+
553
+ {
554
+
555
+ this.service.PreStart();
556
+
557
+ this.service.Register(data);
558
+
559
+
560
+
561
+ //ここでイベントの購読をしたい
562
+
563
+ this.service.instance.OnCallback += Instance_OnCallback;
564
+
565
+ }
566
+
567
+
568
+
569
+ private void Instance_OnCallback(object sender, DataTransferWCFService.CommunicationEventArgs args)
570
+
571
+ {
572
+
573
+ Console.Write(args.Message);
574
+
575
+ }
576
+
577
+
578
+
579
+ public void Clear()
580
+
581
+ {
582
+
583
+ this.service.Clear();
584
+
585
+ }
586
+
587
+ }
588
+
589
+ }
590
+
591
+ ```
592
+
593
+
594
+
595
+ ### 試したこと
596
+
597
+
598
+
599
+ ・上記実装。
600
+
601
+ ・以下のようにイベントを処理するクラスを実装し、DataTransferServiceでそのオブジェクトを保持した。サービスインターフェースにそのオブジェクトを返すようなメソッドを定義し実装したが、期待通りの動作をしてくれなかった。
602
+
603
+ ```C#
604
+
605
+ [DataContract]
606
+
607
+ public class EventHelper
608
+
609
+ {
610
+
611
+ public delegate void CallbackEventHandler(object sender, CommunicationEventArgs args);
612
+
613
+ [field: DataMember]
614
+
615
+ public event CallbackEventHandler OnCallback;
616
+
617
+
618
+
619
+ [OperationContract]
620
+
621
+ public void Fire(UInt32 id, byte[] message)
622
+
623
+ {
624
+
161
625
  this.OnCallback?.Invoke(this, new CommunicationEventArgs(id, message));
162
626
 
163
627
  }
164
628
 
165
-
166
-
167
- public void Register(byte[] data)
168
-
169
- {
170
-
171
- dataList.Add(data);
172
-
173
- }
629
+ }
174
-
175
- }
176
-
177
- }
178
630
 
179
631
  ```
180
632
 
181
633
 
182
634
 
183
- サービスの開始周り(DataTransfer.cs)
184
-
185
- ```C#
186
-
187
- namespace DataTransfer
188
-
189
- {
190
-
191
- public class DataTransfer
192
-
193
- {
194
-
195
- public DataTransferService DataTransferServiceInstance
196
-
197
- {
198
-
199
- get
200
-
201
- {
202
-
203
- return _DataTransfer.dtService;
204
-
205
- }
206
-
207
- }
208
-
209
-
210
-
211
- public void Register(byte[] data)
212
-
213
- {
214
-
215
- _DataTransfer.Register(data);
216
-
217
- }
218
-
219
-
220
-
221
- public void Clear()
222
-
223
- {
224
-
225
- _DataTransfer.Clear();
226
-
227
- }
228
-
229
-
230
-
231
- public byte[] GetResponse(UInt32 id, byte[] request)
232
-
233
- {
234
-
235
- return _DataTransfer.GetResponse(id, request);
236
-
237
- }
238
-
239
- }
240
-
241
-
242
-
243
- static class _DataTransfer
244
-
245
- {
246
-
247
- private static string pipeName = @"net.pipe://sample";
248
-
249
- private static ServiceHost host;
250
-
251
- private static IDataTransferService client;
252
-
253
- static DuplexChannelFactory<IDataTransferService> factory;
254
-
255
- public static DataTransferService dtService = new DataTransferService();
256
-
257
-
258
-
259
- static _DataTransfer()
260
-
261
- {
262
-
263
- host = new ServiceHost(typeof(IDataTransferService), new Uri(pipeName));
264
-
265
-
266
-
267
- host.AddServiceEndpoint(typeof(IDataTransferService), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
268
-
269
- {
270
-
271
- ReceiveTimeout = TimeSpan.MaxValue
272
-
273
- }, string.Empty);
274
-
275
-
276
-
277
- try
278
-
279
- {
280
-
281
- host.Open();
282
-
283
- }
284
-
285
- catch(Exception ex)
286
-
287
- {
288
-
289
- Debug.WriteLine(ex.Message);
290
-
291
- }
292
-
293
-
294
-
295
- Create();
296
-
297
-
298
-
299
- }
300
-
301
-
302
-
303
- public static void Create()
304
-
305
- {
306
-
307
- factory = new DuplexChannelFactory<IDataTransferService>(new InstanceContext(dtService), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
308
-
309
- {
310
-
311
- MaxReceivedMessageSize = Int32.MaxValue
312
-
313
- }, pipeName);
314
-
315
- client = factory.CreateChannel();
316
-
317
- }
318
-
319
-
320
-
321
- public static void Clear()
322
-
323
- {
324
-
325
- try
326
-
327
- {
328
-
329
- client.Clear();
330
-
331
- }
332
-
333
- catch(Exception ex)
334
-
335
- {
336
-
337
- Debug.WriteLine(ex.Message);
338
-
339
- }
340
-
341
- }
342
-
343
-
344
-
345
- public static void Register(byte[] data)
346
-
347
- {
348
-
349
- try
350
-
351
- {
352
-
353
- client.Register(data);
354
-
355
- }
356
-
357
- catch(Exception ex)
358
-
359
- {
360
-
361
- Debug.WriteLine(ex.Message);
362
-
363
- }
364
-
365
- }
366
-
367
-
368
-
369
- public static byte[] GetResponse(UInt32 id, byte[] request)
370
-
371
- {
372
-
373
- try
374
-
375
- {
376
-
377
- return client.GetResponse(id, request);
378
-
379
- }
380
-
381
- catch(Exception ex)
382
-
383
- {
384
-
385
- Debug.WriteLine(ex.Message);
386
-
387
-
388
-
389
- return null;
390
-
391
- }
392
-
393
- }
394
-
395
- }
396
-
397
- }
398
-
399
- ```
400
-
401
-
402
-
403
- WCFの設定ファイル(App.config)
404
-
405
- ```XML
406
-
407
- <?xml version="1.0" encoding="utf-8" ?>
408
-
409
- <configuration>
410
-
411
-
412
-
413
- <appSettings>
414
-
415
- <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
416
-
417
- </appSettings>
418
-
419
- <system.web>
420
-
421
- <compilation debug="true" />
422
-
423
- </system.web>
424
-
425
- <!-- サービス ライブラリ プロジェクトの展開時に、構成ファイルの内容をホストの app.config ファイルに追加する
426
-
427
- 必要があります。System.Configuration は、ライブラリの構成ファイルをサポートしていません。 -->
428
-
429
- <system.serviceModel>
430
-
431
- <services>
432
-
433
- <service name="DataTransferWCFService.DataTransferService">
434
-
435
- <endpoint address="" binding="wsDualHttpBinding" contract="DataTransferWCFService.IDataTransferService">
436
-
437
- <identity>
438
-
439
- <dns value="localhost" />
440
-
441
- </identity>
442
-
443
- </endpoint>
444
-
445
- <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
446
-
447
- <host>
448
-
449
- <baseAddresses>
450
-
451
- <add baseAddress="http://localhost:8733/Design_Time_Addresses/DataTransferWCFService/Service1/" />
452
-
453
- </baseAddresses>
454
-
455
- </host>
456
-
457
- </service>
458
-
459
- </services>
460
-
461
- <behaviors>
462
-
463
- <serviceBehaviors>
464
-
465
- <behavior>
466
-
467
- <!-- メタデータ情報の開示を避けるには、
468
-
469
- 展開する前に下の値を false に設定します -->
470
-
471
- <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
472
-
473
- <!-- デバッグ目的で障害発生時の例外の詳細を受け取るには、
474
-
475
- 下の値を true に設定します。例外情報の開示を避けるには、
476
-
477
- 展開する前に false に設定します -->
478
-
479
- <serviceDebug includeExceptionDetailInFaults="False" />
480
-
481
- </behavior>
482
-
483
- </serviceBehaviors>
484
-
485
- </behaviors>
486
-
487
- </system.serviceModel>
488
-
489
-
490
-
491
- </configuration>
492
-
493
-
494
-
495
- ```
496
-
497
-
498
-
499
- 本体(Program.cs)
500
-
501
- ```C#
502
-
503
- namespace WCFIPC
504
-
505
- {
506
-
507
- class Program
508
-
509
- {
510
-
511
- static void Main(string[] args)
512
-
513
- {
514
-
515
- //1つ目のプロセスでは
516
-
517
- Transfer transfer = new Transfer();
518
-
519
- transfer.Register(new byte[] { 0x12, 0x34, 0x56 });
520
-
521
-
522
-
523
- //2つ目のプロセスでは
524
-
525
- DataTransfer.DataTransfer dataTransfer = new DataTransfer.DataTransfer();
526
-
527
- var response = dataTransfer.GetResponse(0xFF, new byte[] { 0x78, 0x90 });
528
-
529
- }
530
-
531
- }
532
-
533
-
534
-
535
- class Transfer
536
-
537
- {
538
-
539
- public DataTransfer.DataTransfer service = new DataTransfer.DataTransfer();
540
-
541
-
542
-
543
- public void Register(byte[] data)
544
-
545
- {
546
-
547
- this.service.Register(data);
548
-
549
-
550
-
551
- //ここでプロセス間のイベントを購読したい
552
-
553
- this.service.DataTransferServiceInstance.OnCallback += DataTransferServiceInstance_OnCallback;
554
-
555
- }
556
-
557
-
558
-
559
- private void DataTransferServiceInstance_OnCallback(object sender, DataTransferWCFService.CommunicationEventArgs args)
560
-
561
- {
562
-
563
- Console.Write(args.Message);
564
-
565
- }
566
-
567
-
568
-
569
- public void Clear()
570
-
571
- {
572
-
573
- this.service.Clear();
574
-
575
- }
576
-
577
- }
578
-
579
- }
580
-
581
- ```
582
-
583
-
584
-
585
- ### 試したこと
586
-
587
-
588
-
589
- 双方向通信
590
-
591
-
592
-
593
635
  ### 補足情報(FW/ツールのバージョンなど)
594
636
 
595
637
 

1

ソースコードを追加しました。

2019/09/18 12:03

投稿

kaito_19950605
kaito_19950605

スコア4

test CHANGED
File without changes
test CHANGED
@@ -16,10 +16,6 @@
16
16
 
17
17
 
18
18
 
19
- 漠然とした質問で申し訳ございません。
20
-
21
-
22
-
23
19
  ### 発生している問題・エラーメッセージ
24
20
 
25
21
 
@@ -32,14 +28,560 @@
32
28
 
33
29
 
34
30
 
31
+ サービスの定義(IdataTransferService.cs)
32
+
35
33
  ```C#
36
34
 
35
+ namespace DataTransferWCFService
36
+
37
+ {
38
+
39
+ // メモ: [リファクター] メニューの [名前の変更] コマンドを使用すると、コードと config ファイルの両方で同時にインターフェイス名 "IService1" を変更できます。
40
+
41
+ [ServiceContract(CallbackContract = typeof(IGetResponseCallback))]
42
+
43
+ public interface IDataTransferService
44
+
45
+ {
46
+
47
+ // TODO: ここにサービス操作を追加します。
48
+
49
+
50
+
51
+ [OperationContract(IsOneWay = true)]
52
+
53
+ void Register(byte[] data);
54
+
55
+ [OperationContract(IsOneWay = true)]
56
+
37
- ソースコード
57
+ void Clear();
58
+
59
+ [OperationContract]
60
+
61
+ byte[] GetResponse(UInt32 id, byte[] request);
62
+
63
+ }
64
+
65
+
66
+
67
+ // サービス操作に複合型を追加するには、以下のサンプルに示すようにデータ コントラクトを使用します。
68
+
69
+ // プロジェクトに XSD ファイルを追加できます。プロジェクトのビルド後、そこで定義されたデータ型を、名前空間 "DataTransferWCFService.ContractType" で直接使用できます。
70
+
71
+ }
38
72
 
39
73
  ```
40
74
 
41
75
 
42
76
 
77
+ コールバックインターフェースの定義(IGetResponseCallback.cs)
78
+
79
+ ```C#
80
+
81
+ namespace DataTransferWCFService
82
+
83
+ {
84
+
85
+ public interface IGetResponseCallback
86
+
87
+ {
88
+
89
+ [OperationContract(IsOneWay = true)]
90
+
91
+ void GetResponseCallback(UInt32 id, byte[] message);
92
+
93
+ }
94
+
95
+ }
96
+
97
+ ```
98
+
99
+
100
+
101
+ サービスの実装(DataTransferService.cs)
102
+
103
+ ```C#
104
+
105
+ namespace DataTransferWCFService
106
+
107
+ {
108
+
109
+ // メモ: [リファクター] メニューの [名前の変更] コマンドを使用すると、コードと config ファイルの両方で同時にクラス名 "Service1" を変更できます。
110
+
111
+ public class DataTransferService : IDataTransferService, IGetResponseCallback
112
+
113
+ {
114
+
115
+ private static List<byte[]> dataList = new List<byte[]>();
116
+
117
+ public delegate void CallbackEventHandler(object sender, CommunicationEventArgs args);
118
+
119
+ public event CallbackEventHandler OnCallback;
120
+
121
+
122
+
123
+ public void Clear()
124
+
125
+ {
126
+
127
+ dataList.Clear();
128
+
129
+ }
130
+
131
+
132
+
133
+ public byte[] GetResponse(uint id, byte[] request)
134
+
135
+ {
136
+
137
+ IGetResponseCallback callback = OperationContext.Current.GetCallbackChannel<IGetResponseCallback>();
138
+
139
+ byte[] response = dataList.ElementAt((int)id)
140
+
141
+ .Concat(request)
142
+
143
+ .ToArray();
144
+
145
+
146
+
147
+ callback.GetResponseCallback(id, response);
148
+
149
+
150
+
151
+ return response;
152
+
153
+ }
154
+
155
+
156
+
157
+ public void GetResponseCallback(uint id, byte[] message)
158
+
159
+ {
160
+
161
+ this.OnCallback?.Invoke(this, new CommunicationEventArgs(id, message));
162
+
163
+ }
164
+
165
+
166
+
167
+ public void Register(byte[] data)
168
+
169
+ {
170
+
171
+ dataList.Add(data);
172
+
173
+ }
174
+
175
+ }
176
+
177
+ }
178
+
179
+ ```
180
+
181
+
182
+
183
+ サービスの開始周り(DataTransfer.cs)
184
+
185
+ ```C#
186
+
187
+ namespace DataTransfer
188
+
189
+ {
190
+
191
+ public class DataTransfer
192
+
193
+ {
194
+
195
+ public DataTransferService DataTransferServiceInstance
196
+
197
+ {
198
+
199
+ get
200
+
201
+ {
202
+
203
+ return _DataTransfer.dtService;
204
+
205
+ }
206
+
207
+ }
208
+
209
+
210
+
211
+ public void Register(byte[] data)
212
+
213
+ {
214
+
215
+ _DataTransfer.Register(data);
216
+
217
+ }
218
+
219
+
220
+
221
+ public void Clear()
222
+
223
+ {
224
+
225
+ _DataTransfer.Clear();
226
+
227
+ }
228
+
229
+
230
+
231
+ public byte[] GetResponse(UInt32 id, byte[] request)
232
+
233
+ {
234
+
235
+ return _DataTransfer.GetResponse(id, request);
236
+
237
+ }
238
+
239
+ }
240
+
241
+
242
+
243
+ static class _DataTransfer
244
+
245
+ {
246
+
247
+ private static string pipeName = @"net.pipe://sample";
248
+
249
+ private static ServiceHost host;
250
+
251
+ private static IDataTransferService client;
252
+
253
+ static DuplexChannelFactory<IDataTransferService> factory;
254
+
255
+ public static DataTransferService dtService = new DataTransferService();
256
+
257
+
258
+
259
+ static _DataTransfer()
260
+
261
+ {
262
+
263
+ host = new ServiceHost(typeof(IDataTransferService), new Uri(pipeName));
264
+
265
+
266
+
267
+ host.AddServiceEndpoint(typeof(IDataTransferService), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
268
+
269
+ {
270
+
271
+ ReceiveTimeout = TimeSpan.MaxValue
272
+
273
+ }, string.Empty);
274
+
275
+
276
+
277
+ try
278
+
279
+ {
280
+
281
+ host.Open();
282
+
283
+ }
284
+
285
+ catch(Exception ex)
286
+
287
+ {
288
+
289
+ Debug.WriteLine(ex.Message);
290
+
291
+ }
292
+
293
+
294
+
295
+ Create();
296
+
297
+
298
+
299
+ }
300
+
301
+
302
+
303
+ public static void Create()
304
+
305
+ {
306
+
307
+ factory = new DuplexChannelFactory<IDataTransferService>(new InstanceContext(dtService), new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
308
+
309
+ {
310
+
311
+ MaxReceivedMessageSize = Int32.MaxValue
312
+
313
+ }, pipeName);
314
+
315
+ client = factory.CreateChannel();
316
+
317
+ }
318
+
319
+
320
+
321
+ public static void Clear()
322
+
323
+ {
324
+
325
+ try
326
+
327
+ {
328
+
329
+ client.Clear();
330
+
331
+ }
332
+
333
+ catch(Exception ex)
334
+
335
+ {
336
+
337
+ Debug.WriteLine(ex.Message);
338
+
339
+ }
340
+
341
+ }
342
+
343
+
344
+
345
+ public static void Register(byte[] data)
346
+
347
+ {
348
+
349
+ try
350
+
351
+ {
352
+
353
+ client.Register(data);
354
+
355
+ }
356
+
357
+ catch(Exception ex)
358
+
359
+ {
360
+
361
+ Debug.WriteLine(ex.Message);
362
+
363
+ }
364
+
365
+ }
366
+
367
+
368
+
369
+ public static byte[] GetResponse(UInt32 id, byte[] request)
370
+
371
+ {
372
+
373
+ try
374
+
375
+ {
376
+
377
+ return client.GetResponse(id, request);
378
+
379
+ }
380
+
381
+ catch(Exception ex)
382
+
383
+ {
384
+
385
+ Debug.WriteLine(ex.Message);
386
+
387
+
388
+
389
+ return null;
390
+
391
+ }
392
+
393
+ }
394
+
395
+ }
396
+
397
+ }
398
+
399
+ ```
400
+
401
+
402
+
403
+ WCFの設定ファイル(App.config)
404
+
405
+ ```XML
406
+
407
+ <?xml version="1.0" encoding="utf-8" ?>
408
+
409
+ <configuration>
410
+
411
+
412
+
413
+ <appSettings>
414
+
415
+ <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
416
+
417
+ </appSettings>
418
+
419
+ <system.web>
420
+
421
+ <compilation debug="true" />
422
+
423
+ </system.web>
424
+
425
+ <!-- サービス ライブラリ プロジェクトの展開時に、構成ファイルの内容をホストの app.config ファイルに追加する
426
+
427
+ 必要があります。System.Configuration は、ライブラリの構成ファイルをサポートしていません。 -->
428
+
429
+ <system.serviceModel>
430
+
431
+ <services>
432
+
433
+ <service name="DataTransferWCFService.DataTransferService">
434
+
435
+ <endpoint address="" binding="wsDualHttpBinding" contract="DataTransferWCFService.IDataTransferService">
436
+
437
+ <identity>
438
+
439
+ <dns value="localhost" />
440
+
441
+ </identity>
442
+
443
+ </endpoint>
444
+
445
+ <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
446
+
447
+ <host>
448
+
449
+ <baseAddresses>
450
+
451
+ <add baseAddress="http://localhost:8733/Design_Time_Addresses/DataTransferWCFService/Service1/" />
452
+
453
+ </baseAddresses>
454
+
455
+ </host>
456
+
457
+ </service>
458
+
459
+ </services>
460
+
461
+ <behaviors>
462
+
463
+ <serviceBehaviors>
464
+
465
+ <behavior>
466
+
467
+ <!-- メタデータ情報の開示を避けるには、
468
+
469
+ 展開する前に下の値を false に設定します -->
470
+
471
+ <serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
472
+
473
+ <!-- デバッグ目的で障害発生時の例外の詳細を受け取るには、
474
+
475
+ 下の値を true に設定します。例外情報の開示を避けるには、
476
+
477
+ 展開する前に false に設定します -->
478
+
479
+ <serviceDebug includeExceptionDetailInFaults="False" />
480
+
481
+ </behavior>
482
+
483
+ </serviceBehaviors>
484
+
485
+ </behaviors>
486
+
487
+ </system.serviceModel>
488
+
489
+
490
+
491
+ </configuration>
492
+
493
+
494
+
495
+ ```
496
+
497
+
498
+
499
+ 本体(Program.cs)
500
+
501
+ ```C#
502
+
503
+ namespace WCFIPC
504
+
505
+ {
506
+
507
+ class Program
508
+
509
+ {
510
+
511
+ static void Main(string[] args)
512
+
513
+ {
514
+
515
+ //1つ目のプロセスでは
516
+
517
+ Transfer transfer = new Transfer();
518
+
519
+ transfer.Register(new byte[] { 0x12, 0x34, 0x56 });
520
+
521
+
522
+
523
+ //2つ目のプロセスでは
524
+
525
+ DataTransfer.DataTransfer dataTransfer = new DataTransfer.DataTransfer();
526
+
527
+ var response = dataTransfer.GetResponse(0xFF, new byte[] { 0x78, 0x90 });
528
+
529
+ }
530
+
531
+ }
532
+
533
+
534
+
535
+ class Transfer
536
+
537
+ {
538
+
539
+ public DataTransfer.DataTransfer service = new DataTransfer.DataTransfer();
540
+
541
+
542
+
543
+ public void Register(byte[] data)
544
+
545
+ {
546
+
547
+ this.service.Register(data);
548
+
549
+
550
+
551
+ //ここでプロセス間のイベントを購読したい
552
+
553
+ this.service.DataTransferServiceInstance.OnCallback += DataTransferServiceInstance_OnCallback;
554
+
555
+ }
556
+
557
+
558
+
559
+ private void DataTransferServiceInstance_OnCallback(object sender, DataTransferWCFService.CommunicationEventArgs args)
560
+
561
+ {
562
+
563
+ Console.Write(args.Message);
564
+
565
+ }
566
+
567
+
568
+
569
+ public void Clear()
570
+
571
+ {
572
+
573
+ this.service.Clear();
574
+
575
+ }
576
+
577
+ }
578
+
579
+ }
580
+
581
+ ```
582
+
583
+
584
+
43
585
  ### 試したこと
44
586
 
45
587
 
@@ -53,3 +595,5 @@
53
595
 
54
596
 
55
597
  Visual Studio 2019
598
+
599
+ .NET Framework 4.7.2