Как я могу продолжить свое приложение, только когда все асинхронные операции завершены? - PullRequest
3 голосов
/ 20 февраля 2012

В моем приложении я использовал для создания вдоль строки асинхронных операций, которые передаются в функции, подобные этой:

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

Однако теперь я перенес многие из этих асинхронных операций в отдельные классы и объекты, но я хочу получить те же результаты. В основном я переместил эти асинхронные операции в классы, которые стали частью коллекции.

Я бы хотел, чтобы мой новый код выглядел так:

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

Какие вещи мне нужно сделать, чтобы это заработало? Спасибо.


Используя приведенный ниже ответ о Задачах, кажется, что-то все еще не хватает. Программа никогда не продолжается, даже после того, как все было брошено в BackgroundWorker.

Ответы [ 5 ]

4 голосов
/ 20 февраля 2012

Вы можете использовать Task<T> (используя Task Parallel Library для 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();
});
2 голосов
/ 20 февраля 2012

Я не знаком с wp7, но вы можете использовать счетчик в качестве статического поля и проверить, равен ли он 0 в конечном действии.

Каждый MyClass.DoAsyn2 () должен вызывать событие или любой другой кодсигнализировать, что это закончено.

Другой вариант - переместить все асинхронные в задачу и вызвать Task.WaitAll

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

1 голос
/ 21 февраля 2012

Изучив все предыдущие ответы, я не смог решить свою проблему.

Вместо этого мне нужно было создать собственные события в моих классах, которые запускались при успешном завершении асинхронных задач..

Веб-сайт, который оказался наиболее полезным для меня, был: http://www.marten -online.com / csharp / simple-custom-event-processing.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();
                }
            }
        }
1 голос
/ 20 февраля 2012

Вы уже видели CountdownEvent в .Net 4? Это сигнальная конструкция, в которой один поток заблокируется и продолжит работу только после того, как другие потоки завершили и вызвали set для события обратного отсчета. Вы инициализируете его числом сигналов, которое вам нужно, прежде чем поток, вызывающий Wait для конструкции, продолжит работу. E.g.:

 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 секунды, если не получит ответ от всех потоков обработки. В этом случае последнее действие не будет выполнено.

Вы можете воспроизвести это с помощью Monitor / Pulse, если вы не нацеливаетесь на .Net 4.

Вот хороший пример и здесь . Надеюсь, это поможет!

0 голосов
/ 20 февраля 2012

Слышали ли вы о шаблоне Deferred, часто используемом в Javascript?

С ним легко работать, он очень динамичен, и вы также сможете реализовать его на Windows Phone.

Посмотрите это руководство http://twistedmatrix.com/documents/current/core/howto/defer.html

С уважением Tobias

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...