How do I know when my async function is finished? (windows phone7 dev)
This is a Windows Phone7 project. I have a few async calls in my code, that in the end, fills up a List that is global. But my problem is, how do I know when the async jobs is done, so that I can continue in the code? EDIT I updated the code:
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;
});
}
The async calls is done using Action<T>
in .net framework 4. It still doesn't wait for the async call. Is it bec开发者_运维问答ause the async call is done from "GetFlickrPhotos"?
I went for the following code, it's working for my program. Thank you for the help!
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();
}
});
This way, I call the method ShowPhotos()
when the Flickr call is finished.
In the simplest case, you could provide a callback, or with a little more effort, create an event that raised when the work is complete. Here's code for a callback:
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();
}
Look into IAsyncResult
- there are a lot of resources out there related to this particular pattern, but basically this will allow you to maintain an instance of an object who's role it is to allow you to determine the current state of an operation - or even exclusively call an End
method to interrupt an operation.
Your method signatures might look something like this, for instance:
public IAsyncResult BeginOperation(AsyncCallback callback)
public EndOperation(IAsyncResult result)
From MSDN:
The IAsyncResult interface is implemented by classes containing methods that can operate asynchronously. It is the return type of methods that initiate an asynchronous operation, such as IsolatedStorageFileStream.BeginRead, and is passed to methods that conclude an asynchronous operation, such as IsolatedStorageFileStream.EndRead. An IAsyncResult is also passed to the method that is invoked by an AsyncCallback delegate when an asynchronous operation completes.
An object that supports the IAsyncResult interface stores state information for an asynchronous operation, and provides a synchronization object to allow threads to be signaled when the operation completes.
EDIT:
OK, unless I'm missing something then a simple event notification may be all you need here - consider the following usage of a class introduced below:
var flickrOperation = new FlickrOperation();
flickrOperation.FlickrPhotoURLsLoaded +=
delegate(object sender, EventArgs e)
{
var photoCount = flickrOperation.FlickrPhotoURLs.Count;
};
flickrOperation.BeginGetFlickrPhotoURLs();
Now lets define the class, albeit primitive and simply a means to an end in this case. Note, in particular, the declaration an use of FlickrPhotoURLsLoaded
- this is the event which is fired upon completed of the operation (as dictated by the completion of the callback loading the URLs):
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());
}
}
}
精彩评论