2012-02-20 21 views
3

在我的申请,我曾经沿着异步操作的字符串,其在功能通过这样的创造:只有当所有的异步操作完成后,我如何才能让我的应用程序继续运行?

public void LotsOfAsync() 
{ 
    DoAsync1(()=> { DoAsync2(()=> { doAsync3(()=> { finalAction();}) }) }); 
} 

不过,现在我已经感动了很多的异步操作成单独的类和对象,但我想要的相同的结果。主要是我已经将这些异步操作转移到了成为集合一部分的类中。

我想我的新的代码看起来像这样:

public void lotsOfAsync() 
{ 
    DoAsync1(); 
    for each (MyClass in Async1List) 
    { 
      MyClass.DoAsyn2(); 
     } 
    if (allAsyncOperationsAreComplete) 
    { 
     FinalAction(); 
    } 
} 

我需要什么样的事情要做,要得到这个工作?谢谢。


使用低于任务应答,东西似乎仍然缺乏。即使将所有内容都投入到BackgroundWorker后,该程序也不会继续。

回答

4

您可以使用Task<T>(使用Task Parallel Library for Silverlight) - 这样的事情也许:

List<Task> tasks = new List<Task>(); 

Task.Factory.StartNew(() => DoAsync1()).ContinueWith(_ => 
{ 
    foreach (MyClass myClass in Async1List) 
    { 
     tasks.Add(Task.Factory.StartNew(() => myClass.DoSomething())); 
    } 
    Task.WaitAll(tasks.ToArray()); 
    FinalAction(); 
}); 
+0

谢谢,myClass.DoSomething()必须返回任何特殊的东西来工作吗? – Bob 2012-02-20 14:44:28

+0

不,事实上它返回的只是在上面的例子中被忽略 – BrokenGlass 2012-02-20 14:46:09

+1

看起来Windows Phone 7上不存在任务:( – Bob 2012-02-20 14:56:11

2

我不熟悉wp7,但你可以使用计数器作为静态字段,并检查它是否等于0在最后的行动。

每个MyClass.DoAsyn2()都应该触发一个事件或任何其他代码来表示它已完成。

另一种选择是将所有异步移动到任务,并呼吁Task.WaitAll

http://msdn.microsoft.com/en-us/library/dd270695.aspx

+0

确定这是不是我的小费,甚至更好,它几乎推迟已经实施并准备使用。 – Tobias 2012-02-20 13:18:56

+0

这是正确的答案,但它并没有帮助我理解如何解决这些事件。如果你解释这些部分,我可以接受它。 – Bob 2012-02-21 13:11:42

1

你吃过看看在.Net 4的CountdownEvent?这是一个信号结构,其中一个线程将被阻塞,并且只有在其他线程完成并在倒计数事件上调用set时才会继续。在构造上的线程调用Wait将继续之前,使用需要的信号数量初始化它。例如: -

CountdownEvent countdown = new CountdownEvent(3); 

只会让线程调用Wait进行一次3其他线程呼吁Signal

所以,你的例子或许会是这个样子:

public void lotsOfAsync()  
{ 
    Int32 numberOfAsyncProcesses = Async1List.Length + 1;   
    CountdownEvent countdown = new CountdownEvent (numberOfAsyncProcesses); 

    DoAsync1(countdown); // call countdown.signal() in the async method once complete. 

    for each (MyClass in Async1List)   
    { 
     // call countdown.signal() in the async method once complete. 
     MyClass.DoAsyn2(countdown);   
    } 

    if(countDown.Wait(TimeSpan.FromSeconds(3)) 
    {    
     FinalAction();  
    } 
} 

我还添加了超时,此时调用线程将在3秒后如果未能获得所有处理线程的响应解除。在这种情况下,最终的操作将不会执行。

你可以,如果你的目标不是.NET 4

有一个很好的例子here也与监视器/脉冲重现此。希望这可以帮助!

+0

你知道windows phone sdk是否支持.Net 4?我尝试过使用await和异步之前,但得到错误,关键字无法识别。 – Bob 2012-02-20 14:45:25

+1

但是,不幸的是,您可以自己实现相同的功能 - 请参阅:http://stackoverflow.com/questions/8879870/syncronizing-actions-in-silverlight – Jeb 2012-02-20 16:05:12

1

看完所有以前的答案后,我无法解决我的问题。

相反,我需要做的是在我的类中创建自定义事件,这些事件在成功完成异步任务时触发。

被证明是最有用的给我来完成,这是该网站:http://www.marten-online.com/csharp/simple-custom-event-handling.html

我的最终代码看起来是这样的:

public void lotsOfAsync() 
{ 
    DoAsync1(); 
    for each (MyClass in Async1List) 
    {  
      MyClass.PropertyChange += new MyClass.PropertyChangeHandler(Async2Complete); 
      MyClass.DoAsyn2(); 
     } 
} 

public void Async2Complete(object sender, PropertyChangeEventArgs data) 
     { 
      if (data.PropertyName == "AsyncComplete") 
      { 
       totalAsyncCompleted++; 
       if (totalAsyncCompleted >= Async1List.Count) 
       { 
        FinalAction(); 
       } 
      } 
     } 
+0

注意:我会使用Interlocked.Increment(ref totalAsyncCompleted)since一个增量不是一个原子操作(一个读操作后跟一个修改,然后是写指令,这些操作可能被预先占用)。 – Jeb 2012-02-21 19:08:23

+0

@JohnParr谢谢 – Bob 2012-02-21 20:26:21

相关问题