C# 如何正确连接多个异步方法的结果?

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

在Silverlight应用程序中,我需要并行运行多个异步调用-它们将调用服务器来检查数据等。我的伪代码设置如下所示

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 */ });