我有几个WCF调用,比如A,B,C,D,E。它们在SL应用程序中(所以我想我必须小心线程等)。
我希望B在A完成后运行,而C可以与它们并发运行。我希望D在所有三个完成之后运行。另外基于一个条件(简单的如果......)我也想要E运行(与上述任何一个同时发生)。
我刚刚下载了Rx,觉得它是这项工作的工具。但是,我还没有掌握所有的操作员和技巧等。
可以这样做吗?怎么样?请解释为此所需的操作员。
编辑添加:为简单起见,我们假设所有这些服务都将字符串(或int)作为参数,并返回实现复杂接口的内容,因此事件很简单EventHandlers (非泛型),我将它们转换为处理程序代码中的特殊接口 一些输入在开始时可用,一些来自先前服务的结果(例如,B的输入字符串是根据A的结果计算的)
答案 0 :(得分:2)
我已将编辑考虑在内并制定了解决方案。
我不得不说微软在Silverlight中编写简单的WCF调用非常困难。处理事件以从异步调用中获取返回数据真是太痛苦了。
话虽如此,通过一些“复制并粘贴”的样板代码,Rx可以很好地消除复杂性。
以下是我提出的最终客户端代码:
var service = new Service1Client();
var abs =
from a in service.AObservable("a")
from b in service.BObservable(a)
select new { a, b };
var cs = service.CObservable("c");
var abcs = abs.Zip(cs, (ab, c) => new { ab.a, ab.b, c });
var ds =
from abc in abcs
from d in service.DObservable(abc.a, abc.b, abc.c)
select String.Format(
"A={0} B={1} C={2} D={3}",
abc.a, abc.b, abc.c, d);
var condition = true;
var es = from e in condition
? service.EObservable("e")
: Observable.Empty<string>()
select String.Format("E={0}", e);
ds.Merge(es).ObserveOnDispatcher()
.Subscribe(r => this.label1.Content += " " + r);
一方面,这段代码并不像我希望的那么漂亮,但另一方面,我认为我不能让它变得更好。希望你能看到你的要求是如何得到满足的。
现在有了坏消息 - 必须为每个服务代理创建扩展方法。定义EventArgs
的方式无法在不使用特定服务引用类作为扩展方法的this
参数的情况下获得结果。
从好的方面来看,虽然代码主要是“复制并粘贴”,但很少有修改。
此外,您需要创建与您使用的参数一样多的扩展方法以及一个。
以下是我需要为示例代码定义的扩展方法:
public static class Service1ClientEx
{
public static Func<IObservable<R>> ToObservableFunc<EA, R>(this Service1Client service, Action<Service1Client> async, Action<Service1Client, EventHandler<EA>> ah, Action<Service1Client, EventHandler<EA>> rh, Func<EA, R> resultSelector)
where EA : System.ComponentModel.AsyncCompletedEventArgs
{
return () => Observable.Create<R>(o =>
{
var response =
from ep in Observable.FromEventPattern<EA>(h => ah(service, h), h => rh(service, h))
select resultSelector(ep.EventArgs);
var subscription = response.Take(1).Subscribe(o);
async(service);
return subscription;
}).ObserveOn(Scheduler.ThreadPool);
}
public static Func<P0, IObservable<R>> ToObservableFunc<P0, EA, R>(this Service1Client service, Action<Service1Client, P0> async, Action<Service1Client, EventHandler<EA>> ah, Action<Service1Client, EventHandler<EA>> rh, Func<EA, R> resultSelector)
where EA : System.ComponentModel.AsyncCompletedEventArgs
{
return p0 => Observable.Create<R>(o =>
{
var response =
from ep in Observable.FromEventPattern<EA>(h => ah(service, h), h => rh(service, h))
select resultSelector(ep.EventArgs);
var subscription = response.Take(1).Subscribe(o);
async(service, p0);
return subscription;
}).ObserveOn(Scheduler.ThreadPool);
}
public static Func<P0, P1, IObservable<R>> ToObservableFunc<P0, P1, EA, R>(this Service1Client service, Action<Service1Client, P0, P1> async, Action<Service1Client, EventHandler<EA>> ah, Action<Service1Client, EventHandler<EA>> rh, Func<EA, R> resultSelector)
where EA : System.ComponentModel.AsyncCompletedEventArgs
{
return (p0, p1) => Observable.Create<R>(o =>
{
var response =
from ep in Observable.FromEventPattern<EA>(h => ah(service, h), h => rh(service, h))
select resultSelector(ep.EventArgs);
var subscription = response.Take(1).Subscribe(o);
async(service, p0, p1);
return subscription;
}).ObserveOn(Scheduler.ThreadPool);
}
public static Func<P0, P1, P2, IObservable<R>> ToObservableFunc<P0, P1, P2, EA, R>(this Service1Client service, Action<Service1Client, P0, P1, P2> async, Action<Service1Client, EventHandler<EA>> ah, Action<Service1Client, EventHandler<EA>> rh, Func<EA, R> resultSelector)
where EA : System.ComponentModel.AsyncCompletedEventArgs
{
return (p0, p1, p2) => Observable.Create<R>(o =>
{
var response =
from ep in Observable.FromEventPattern<EA>(h => ah(service, h), h => rh(service, h))
select resultSelector(ep.EventArgs);
var subscription = response.Take(1).Subscribe(o);
async(service, p0, p1, p2);
return subscription;
}).ObserveOn(Scheduler.ThreadPool);
}
public static Func<P0, P1, P2, P3, IObservable<R>> ToObservableFunc<P0, P1, P2, P3, EA, R>(this Service1Client service, Action<Service1Client, P0, P1, P2, P3> async, Action<Service1Client, EventHandler<EA>> ah, Action<Service1Client, EventHandler<EA>> rh, Func<EA, R> resultSelector)
where EA : System.ComponentModel.AsyncCompletedEventArgs
{
return (p0, p1, p2, p3) => Observable.Create<R>(o =>
{
var response =
from ep in Observable.FromEventPattern<EA>(h => ah(service, h), h => rh(service, h))
select resultSelector(ep.EventArgs);
var subscription = response.Take(1).Subscribe(o);
async(service, p0, p1, p2, p3);
return subscription;
}).ObserveOn(Scheduler.ThreadPool);
}
public static IObservable<string> AObservable(this Service1Client service, string data)
{
return service
.ToObservableFunc<string, ACompletedEventArgs, string>((s, p0) => s.AAsync(p0), (s, h) => s.ACompleted += h, (s, h) => s.ACompleted -= h, ea => ea.Result)
.Invoke(data);
}
public static IObservable<string> BObservable(this Service1Client service, string data)
{
return service
.ToObservableFunc<string, BCompletedEventArgs, string>((s, p0) => s.BAsync(p0), (s, h) => s.BCompleted += h, (s, h) => s.BCompleted -= h, ea => ea.Result)
.Invoke(data);
}
public static IObservable<string> CObservable(this Service1Client service, string data)
{
return service
.ToObservableFunc<string, CCompletedEventArgs, string>((s, p0) => s.CAsync(p0), (s, h) => s.CCompleted += h, (s, h) => s.CCompleted -= h, ea => ea.Result)
.Invoke(data);
}
public static IObservable<string> DObservable(this Service1Client service, string dataA, string dataB, string dataC)
{
return service
.ToObservableFunc<string, string, string, DCompletedEventArgs, string>((s, p0, p1, p2) => s.DAsync(p0, p1, p2), (s, h) => s.DCompleted += h, (s, h) => s.DCompleted -= h, ea => ea.Result)
.Invoke(dataA, dataB, dataC);
}
public static IObservable<string> EObservable(this Service1Client service, string data)
{
return service
.ToObservableFunc<string, ECompletedEventArgs, string>((s, p0) => s.EAsync(p0), (s, h) => s.ECompleted += h, (s, h) => s.ECompleted -= h, ea => ea.Result)
.Invoke(data);
}
}
像我说的那样痛苦。
你当然不必创建这些类型的扩展方法来在Silverlight中使用Rx和WCF,但我觉得一旦你创建了它们,那么客户端代码变得更容易使用。
如果您需要更多解释,请告诉我。