Rxについて頭を悩ませようとしているだけです
Rx を使用して 2 秒ごとに Web サイトをポーリングしています
var results = new List<MyDTO>();
var cx = new WebserviceAPI( ... );
var callback = cx.GetDataAsync().Subscribe(rs => { results.AddRange(rs); });
var poller = Observable.Interval(TimeSpan.FromSeconds(2)).Subscribe( _ => { cx.StartGetDataAsync(); });
(Web サービス API は、observable を作成する getItemsAsync/getItemsCompleted イベント ハンドラー タイプのメカニズムを公開します)。
Web サイトが戻ってきたら、応答の「ビジネス部分」を DTO の IEnumerable にアンパックしています。
public IObservable<IEnumerable<MyDTO>> GetDataAsync()
{
var o = Observable.FromEventPattern<getItemsCompletedEventHandler,getItemsCompletedEventArgs>(
h => _webService.getItemsCompleted += h,
h => _webService.getItemsCompleted -= h);
return o.Select(c=> from itm in c.EventArgs.Result.ItemList
select new MyDTO()
{
...
});
}
私の推論は、すべてのデータが文字列内にあることを考えると、そこにパックして IEnumerable にすることは理にかなっているということです...しかし、それが正しいかどうかはわかりません!
Web サイトの応答に 2 秒以上かかる場合は、MSTest がクラッシュしていることがわかります。デバッグ時に生成されるエラーは
「非同期処理中にエラーが発生しました。複数の非同期同時操作を未処理にするには、一意の状態オブジェクトが必要です」
内部例外あり
「アイテムは既に追加されています。辞書のキー: 'System.Object' 追加中のキー: 'System.Object'」
問題は、前の呼び出しがデータの入力を完了する前に次の呼び出しが開始され、データが返されるという再入可能性の 1 つであると想定しています。
だからかどうかはわかりません
- 私は物事を非常に正しくまとめました
- 再入を避けるために、何らかの方法で接続を調整する必要があります。
- IEnumerable の代わりに別の中間データ構造 (またはメカニズム) を使用する必要があります
いくつかのガイダンスをいただければ幸いです。
編集 1: Web 呼び出しを変更して、一意の状態オブジェクトを含めるようにしました
public void StartGetDataAsync()
{
...
// was: _webService.getItemsAsync(request);
_webService.getItemsAsync(request, Guid.NewGuid());
}
そしてそれを機能させました。しかし、それが正しい方法であるかどうかはまだわかりません
編集 2 - Web サービス sigs: webServiceApi クラスがラップする SOAP Web サービスを使用しています。作成された references.cs には、次のメソッドが含まれています。
public void getItemsAsync(GetItemsReq request, object userState)
{
if ((this.getItemsOperationCompleted == null))
{
this.getItemsOperationCompleted = new System.Threading.SendOrPostCallback(this.OngetItemsOperationCompleted);
}
this.InvokeAsync("getItems", new object[] {
request}, this.getItemsOperationCompleted, userState);
}
private System.Threading.SendOrPostCallback getItemsOperationCompleted;
public event getItemsCompletedEventHandler getItemsCompleted;
public delegate void getItemsCompletedEventHandler(object sender, getItemsCompletedEventArgs e);
public partial class getItemsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs
{
...
}
private void OngetItemsOperationCompleted(object arg)
{
if ((this.getItemsCompleted != null))
{
System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
this.getItemsCompleted(this, new getItemsCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
}
}
おそらく与えすぎた(または何かを逃した)でしょう!
どうも