Как узнать, когда моя асинхронная функция завершена?(Windows Phone7 Dev) - PullRequest
0 голосов
/ 26 марта 2011

Это проект Windows Phone7. В моем коде есть несколько асинхронных вызовов, которые в итоге заполняют глобальный список. Но моя проблема в том, как узнать , когда выполнено асинхронное задание, чтобы я мог продолжить работу с кодом? РЕДАКТИРОВАТЬ Я обновил код:

 private void GetFlickrPhotos(Action finishedCallback)
    {
        Action<FlickrResult<PhotoCollection>> getPhotoCollectionCallback;
        getPhotoCollectionCallback = GetPhotoCollection;
        flickr.InterestingnessGetListAsync(getPhotoCollectionCallback);
        finishedCallback();
    }

    private void GetPhotoCollection(FlickrResult<PhotoCollection> photoColl)
    {
        PhotoCollection photoCollection = (PhotoCollection)photoColl.Result;

        foreach (Photo photo in photoCollection)
        {
            flickrPhotoUrls.Add(photo.MediumUrl);
        }           
    }

    private void Grid_Loaded(object sender, RoutedEventArgs e)
    {
        GetFlickrPhotos(() =>
        {
            int test = flickrPhotoUrls.Count;
        });            
    }

Асинхронные вызовы выполняются с использованием Action<T> в .net framework 4. Он все еще не ожидает асинхронного вызова. Это потому, что асинхронный вызов выполняется из «GetFlickrPhotos»?

Ответы [ 3 ]

1 голос
/ 04 апреля 2011

Я пошел за следующий код, он работает для моей программы. Спасибо за помощь!

 app.Flickr.PhotosSearchAsync(options, flickrResult =>
            {
                if (flickrResult.HasError)
                {                                          
                    ShowErrorImage();
                }
                else 
                {                        
                    flickrPhotoUrls.Clear();
                    flickrImages.Clear();
                    foreach (var item in flickrResult.Result)
                    {
                        FlickrImage image = new FlickrImage();
                        image.ImageOwner = item.OwnerName;
                        image.DateTaken = item.DateTaken;
                        if (item.Title == string.Empty)
                        {
                            image.ImageTitle = "Untitled";
                        }
                        else
                        {
                            image.ImageTitle = item.Title;
                        }
                        image.SmallUrl = item.SmallUrl;
                        image.MediumUrl = item.MediumUrl;
                        image.Description = item.Description;
                        image.Latitude = item.Latitude;
                        image.Longitude = item.Longitude;
                        if (item.DoesLargeExist == true)
                        {
                            image.LargeUrl = item.LargeUrl;
                        }

                        flickrImages.Add(image);
                    }
                    ShowPhotos();
                }                    
            });

Таким образом, я вызываю метод ShowPhotos() после завершения вызова Flickr.

0 голосов
/ 26 марта 2011

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

private void Grid_Loaded(object sender, RoutedEventArgs e)
{
    DoAsyncWork(()=>{
        //continue here
    });

}

private void DoAsyncWork(Action finishedCallback)
{
    //Doing some async work, and in the end of the last async call, 
    //a global List<string> myList is filled
    //at this point call:
    //finishedCallback();
}
0 голосов
/ 26 марта 2011

Посмотрите на IAsyncResult - есть много ресурсов, связанных с этим конкретным шаблоном, но в основном это позволит вам поддерживать экземпляр объекта, роль которого он должен позволить вам определить текущее состояниеоперация - или даже вызывать метод End исключительно для прерывания операции.

Ваши сигнатуры методов могут выглядеть примерно так, например:

public IAsyncResult BeginOperation(AsyncCallback callback)

public EndOperation(IAsyncResult result)

От MSDN :

Интерфейс IAsyncResult реализован с помощью классов, содержащих методы, которые могут работать асинхронно.Это возвращаемый тип методов, которые инициируют асинхронную операцию, например IsolatedStorageFileStream.BeginRead, и передаются методам, которые завершают асинхронную операцию, например IsolatedStorageFileStream.EndRead.IAsyncResult также передается методу, который вызывается делегатом AsyncCallback после завершения асинхронной операции.

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

РЕДАКТИРОВАТЬ:

ОК, если я что-то упустил, тогда простое уведомление о событии может быть все, что вам нужно здесь- рассмотрим следующее использование класса, представленного ниже:

var flickrOperation = new FlickrOperation();
flickrOperation.FlickrPhotoURLsLoaded += 
    delegate(object sender, EventArgs e)
    {
        var photoCount = flickrOperation.FlickrPhotoURLs.Count;
    };
flickrOperation.BeginGetFlickrPhotoURLs();

Теперь давайте определим класс, хотя и примитивный, и просто средство для достижения цели в этом случае.Обратите внимание, в частности, на объявление использования FlickrPhotoURLsLoaded - это событие, которое вызывается после завершения операции (как продиктовано завершением обратного вызова, загружающего URL-адреса):

class FlickrOperation
{
    //the result:
    //ultimately, hide this and expose a read only collection or something
    public List<string> FlickrPhotoURLs = new List<string>();
    //the event:
    //occurs when all returns photo URLs have been loaded
    public event EventHandler FlickrPhotoURLsLoaded;

    public void BeginGetFlickrPhotoURLs()
    {
        //perform the flickr call...
        var getPhotoCollectionCallback = GetFlickrPhotoURLsCallback;
        flickr.InterestingnessGetListAsync(getPhotoCollectionCallback);
    }

    private void GetFlickrPhotoURLsCallback(FlickrResult<PhotoCollection> result)
    {
        //perform the url collection from flickr result...
        FlickrPhotoURLs.Clear();
        var photoCollection = (PhotoCollection)result.Result;
        foreach (Photo photo in photoCollection)
        {
            flickrPhotoUrls.Add(photo.MediumUrl);
        }
        //check to see if event has any subscribers...
        if (FlickrPhotoURLsLoaded != null)
        {
            //invoke any handlers delegated...
            FlickrPhotoURLsLoaded(this, new EventArgs());
        }
    }
}
...