C# 如何正确连接多个异步方法的结果?
在Silverlight应用程序中,我需要并行运行多个异步调用-它们将调用服务器来检查数据等。我的伪代码设置如下所示C# 如何正确连接多个异步方法的结果?,c#,.net,silverlight,asynchronous,parallel-processing,C#,.net,Silverlight,Asynchronous,Parallel Processing,在Silverlight应用程序中,我需要并行运行多个异步调用-它们将调用服务器来检查数据等。我的伪代码设置如下所示 public interface IAsyncVerifier { event EventHandler OnCompleted; void Verify(); } // Subscribe to verifier completion events foreach (var verifier in this.VerifierEngine.GetVerifie
public interface IAsyncVerifier
{
event EventHandler OnCompleted;
void Verify();
}
// Subscribe to verifier completion events
foreach (var verifier in this.VerifierEngine.GetVerifiers())
{
var asyncVerifier = verifier as IAsyncVerifier;
if (asyncVerifier == null || !asyncVerifier.IsVerifierRunning()) continue;
asyncVerifier.OnCompleted += (s, a) => DoWhat(); // ????????
asyncVerifier.Verify();
}
所以,在我看来,所有这些任务都有一个通用的接口。然后在执行之前,我订阅了他们所有的事件和
我需要以某种方式等待他们完成并继续我正在做的事情。如何正确地编写剩余的代码?我看到了某种类型的计数器
,每次调用Verify()
时都会递增,每次完成时都会递减。但我不知道怎么把它包起来,这样它就不会有味道了。另外,如果我理解正确,Silverlight会在后台线程上运行这些线程(调用WCF服务)
编辑:
我正在使用第三方验证引擎this.Verifier.VerifierEngine
不是我写的东西。我只能向集合中添加验证程序。通常,它们在主线程上执行,以验证属性等。我需要创建一个验证器,用于回调服务器,从而在Silverlight中实现async
。我不是手动处理线程,当我调用服务时,它会在主线程上返回,所以很好,这部分对我来说是隐藏的。我所希望的是能够“等待”,直到所有的验证器都完成。我现在唯一能检查的方法就是我现在所做的
因此,我的UI很古怪。用户在修改完字段并开始验证后点击“保存”。我检查是否所有验证器都在验证运行
,并向用户发送需要重试的消息。我真的需要能够等待所有的完成,然后继续
我不需要担心线程,除非正确的解决方案涉及到使用线程
我已经可以查看结果了
Silverlight确实有这样的功能,可以满足您的需要。但是,代码需要看起来与现有代码不同
你不想使用计数器和自旋环有什么特别的原因吗?它虽然不那么漂亮,但也不需要像其他方法那样需要太多的代码更改
Erick我使用Linq来接收
使用System.Reactive.Linq;
可观察的事件
压缩方法
var InitNetCellCache = InitNetCell();
InitNetCellCache.Subscribe((s) =>
{
Debug.WriteLine("init NetCell Cache OK.");
//ScheduleCrrentThread(innerAction);
});
var InitKPIMapCache = InitKPIMapCell();
var zipped = InitKPIMapCache.Zip(InitNetCellCache, (left, right) => left + " - " + right);
zipped.Subscribe((s) =>
{
//When all async methods are completed
runtime.Show();
}
);
IObservable<object> InitNetCell()
{
IUnityContainer unityContainer = ServiceLocator.Current.GetInstance<IUnityContainer>();
INetCellManager inc = unityContainer.Resolve<INetCellManager>();
var NetCell = Observable.FromEvent<InitCacheCompletedDelegate, object>(
h => ((object sendera) => h.Invoke(sendera)),
h => inc.InitCacheCompleted += h,
h => inc.InitCacheCompleted -= h);
//Run you async method
inc.InitCache();
return from e in NetCell select e;
}
var InitNetCellCache=InitNetCell();
InitNetCellCache.Subscribe((s)=>
{
WriteLine(“initnetcell缓存正常”);
//ScheduleCrrentThread(内部操作);
});
var InitKPIMapCache=InitKPIMapCell();
var zipped=InitKPIMapCache.Zip(InitNetCellCache,(左、右)=>left+“-”+right);
压缩。订阅((s)=>
{
//当所有异步方法完成时
runtime.Show();
}
);
IObservable InitNetCell()
{
IUnityContainer unityContainer=ServiceLocator.Current.GetInstance();
INetCellManager inc=unityContainer.Resolve();
var NetCell=Observable.FromEvent(
h=>((对象sendera)=>h.Invoke(sendera)),
h=>inc.InitCacheCompleted+=h,
h=>inc.InitCacheCompleted-=h);
//运行异步方法
inc.InitCache();
从NetCell中的e返回选择e;
}
据我所知,我认为一个简单的计数器就足够了。现在,我将使用最接近您所发布内容的解决方案,并列出为使其工作所需的有效假设。如果任何假设无效,请告诉我,我会适当地更新代码
如果您的循环在UI线程上运行,则可以如下所示。这里有几个假设。首先,我们在UI线程上,验证调用在UI线程上执行。这将使DispatcherSynchronizationContext生效。wcf中的完成事件将在其开始的同步上下文中执行。这将有效地序列化它们的执行,从而使代码具有非常单线程的行为,因此计数器上不需要锁定/etc。这里有更多关于这个的内容。第二个假设是验证调用将始终完成,即使它们出错
编辑以符合退订要求。容忍任何打字错误,因为我只是用记事本来做这个。EventHandler可能必须是特定类型的事件处理程序,具体取决于事件参数
int activeVerifiers = 0;
List<VerificationCleanup> cleanups = new List<VerificationCleanup>();
EventHandler completionHandler = (s, a) =>
{
activeVerifiers--;
if(activeVerifiers == 0)
{
//execute some sort of message/notification/all complete event
foreach(VerificationCleanup cleanup in cleanups)
{
cleanup.Cleanup();
}
}
};
foreach (var verifier in this.VerifierEngine.GetVerifiers())
{
var asyncVerifier = verifier as IAsyncVerifier;
if (asyncVerifier == null || !asyncVerifier.IsVerifierRunning()) continue;
cleanups.Add(new VerificationCleanup(completionHandler, asyncVerifier));
activeVerifiers++;
asyncVerifier.OnCompleted += completionHandler
asyncVerifier.Verify();
}
private class VerificationCleanup
{
private EventHandler eventHandler = null;
private IAsyncVerifier verifier = null;
public VerificationCleanup(EventHandler eventHandler, IAsyncVerifier verifier)
{
this.eventHandler = eventHandler;
this.verifier = verifier;
}
public void Cleanup()
{
if(this.verifier != null)
{
this.verifier.OnCompleted -= this.eventHandler;
}
}
}
int-activeVerifiers=0;
列表清理=新列表();
EventHandler completionHandler=(s,a)=>
{
活动验证器--;
如果(activeVerifiers==0)
{
//执行某种消息/通知/全部完成事件
foreach(清理中的验证清理)
{
cleanup.cleanup();
}
}
};
foreach(此.VerifierEngine.GetVerifiers()中的var验证器)
{
var asyncVerifier=作为IAsyncVerifier的验证器;
如果(asyncVerifier==null | |!asyncVerifier.IsVerifierRunning())继续;
添加(新的VerificationCleanup(completionHandler,asyncVerifier));
activeVerifiers++;
asyncVerifier.OnCompleted+=completionHandler
asyncVerifier.Verify();
}
私有类验证清理
{
私有EventHandler EventHandler=null;
专用IAsyncVerifier验证器=null;
公共验证清理(EventHandler EventHandler、IAsyncVerifier验证程序)
{
this.eventHandler=eventHandler;
this.verifier=验证器;
}
公共空间清理()
{
if(this.verifier!=null)
{
this.verifier.OnCompleted-=this.eventHandler;
}
}
}
我也建议使用反应式框架(Rx)来做你想做的事情
首先,您需要一个函数,该函数将IAsyncVerifier
转换为一个可观察对象,启动验证过程并订阅OnCompleted
。这是:
Func<IAsyncVerifier, IObservable<Unit>> startVerifier = av =>
Observable.Create<Unit>(o =>
{
var subject = new AsyncSubject<Unit>();
var s1 =
Observable
.FromEventPattern(
h => av.OnCompleted += h,
h => av.OnCompleted -= h)
.Select(_ => Unit.Default)
.Subscribe(subject);
var s2 = subject.Subscribe(o);
av.Verify();
return new CompositeDisposable(s1, s2);
});
在Rx世界中,由于这是一个SelectMany
查询,因此默认为ru
var query = (
from av in VerifierEngine
.GetVerifiers()
.OfType<IAsyncVerifier>()
.ToObservable()
where !av.IsVerifierRunning()
from result in startVerifier(av)
select av)
.ToArray();
query.Subscribe(avs => DoWhat());
query.Subscribe(av => { /* Each */ }, () => { /* All */ });