Troubles preforming searching in Windows Phone 7 API

Jul 6, 2011 at 10:38 PM

I'm trying to consume the FlickrNetAPI for Win Phone 7, and I'm getting timeous (currently set to 15 seconds)

Can anyone offer insight as to why my lambda is never being run as a callback from PhotosSearchAsync?

It's important to note this same code works fine in a WPF application, do I need to do something different for a phone application?

        public Task<IEnumerable<string>> GetPhotoCollectionAsync(
            string searchTags,
            int resultQuantityDesired,
            int searchPage, 
            CancellationToken token)
        {
            var tcs = new TaskCompletionSource<IEnumerable<string>>();
 
            //sanity check
            if (String.IsNullOrEmpty(searchTags.Trim()))
            {
                throw new ArgumentException(
                    Settings.Default.FlickrImageServiceSearchTagsErrorMessage,
                    "searchTags");
            }
 
            GetFlickrContext().PhotosSearchAsync(
                new PhotoSearchOptions()
                {
                    PerPage = resultQuantityDesired,
                    Page = searchPage,
                    Tags = searchTags
                },
                (flickrResult) => tcs.SetResult(from photo in flickrResult.Result
                                          select photo.PhotoId));
 
            return tcs.Task;
        }
Coordinator
Jul 7, 2011 at 8:50 AM

With parallel library are you using?

I added the Task Parallel Library for WP7 and got the code to run.

But then I get an InvalidOperationException on the tcs.SetResults line saying that "The underlying Task is already in one of the three final states: RanToCompletion, Faulted, or Canceled.". I don't know enough about parallel tasks to know what this means unfortunately, but the flickrResult had successfully returned a valid photo collection.

Is that any help?

Sam

Jul 7, 2011 at 5:10 PM

I'm using the async CTP, but that's built on TPL.  Either way, I never GET to that line of code... (the tcs.SetResult)

Coordinator
Jul 7, 2011 at 5:43 PM

I don't have the Async CTP installed - I'll try and get it installed at some point and try to reproduce.

Are you using Task.Start() to run the task?

Sam

Jul 7, 2011 at 6:00 PM

Why would I need to? I'm relying on the asynchrony of the PhotosSearchAsync method.  I'm just creating a Task via a TCS to wrap the return of the callback.

Coordinator
Jul 7, 2011 at 6:17 PM

Well you have to actually 'run' the task at some point don't you. If I've got this wrong then I obviously don't understand the Async CTP. I haven't used it before I'm afraid.

Sam

Jul 7, 2011 at 7:44 PM

Honestly, this has nothing to do with the async ctp, First, threads are not tasks, tasks are an abstraction over long-running operations.  In this case, i'm creating a Task representation from a TaskCompletionSource, which has it's Task.Result property set via the tcs.SetResult(...) call, this will set the Task's state to Completed.  I'm not spinning up a thread, the asyncrony only operates on the call to PhotosSearchAsync.

 

Either way, this doesn't appear to be an issue with the tasks or anything, as debugging shows that after I call this:

 

 GetFlickrContext().PhotosSearchAsync(
                new PhotoSearchOptions()
                {
                    PerPage = resultQuantityDesired,
                    Page = searchPage,
                    Tags = searchTags
                },
                (flickrResult) => tcs.SetResult(from photo in flickrResult.Result
                                          select photo.PhotoId));
 

PhotosSearchAsync begins, but the callback is never... called... back... (I've set a breakpoint on the lambda, it never executes, but the call to PhotosSearchAsync has.)

The real question is, why is PhotosSearchAsync never calling me back! D:  Is it avoiding me?  Was I that creepy guy at the party that doesn't know he's creepy or is she just busy? Maybe she lost her phone!  Maybe she... oh wait sorry... flickr.


Jul 7, 2011 at 9:06 PM

New Sample:

 

        private void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
 
            var FlickrContext = new Flickr(Settings.Default.FlickrImageServiceKey, Settings.Default.FlickrImageServiceSecret);
            FlickrContext.PhotosSearchAsync(
                new PhotoSearchOptions()
                {
                    PerPage = 1,
                    Page = 1,
                    Tags = "Test"
                },
                (flickrResult) => Console.WriteLine(flickrResult.Result.Count));
 
            Thread.Sleep(5000);
	}
Coordinator
Jul 7, 2011 at 10:47 PM

I'm assuming that this still exhibits the timeout issue?

If so then it must be a network issue, as there is no difference in the code between the WP7 version and any other version. I have working code here that works fine in WP7 (emulator and real device).

Have you tried firing up Fiddler and seeing what network traffic you are seeing? If the code comes out of the emulator then you should see it there.

Anything else that might be affecting it?

Sam

Jul 8, 2011 at 12:22 AM

seems it's not playing well from a UI thread, also there are some issues with Tasks in WinPhone 7 it seems, I'll keep investigating, I found a way to work it.

Coordinator
Jul 8, 2011 at 7:03 AM

Mmmnn. I know my code uses HttpWebRequest, which does have some issues to do with using the UI Thread rather than a background thread. I had planned to change it to use WebClient soon, but I didn't think it actually stopped the code from working or cause it to timeout, just block the UI a bit - as I said, I've got code here that works fine for me.

If you find anything else then let me know.

Sam

Jul 8, 2011 at 6:05 PM

I may end up debugging it on my end.

Jul 8, 2011 at 6:17 PM
Edited Jul 8, 2011 at 6:59 PM

I think I may have figured it out, it's a scheduling thing, and I didn't make the issue obvious to you either.

 

(flickrResult) => tcs.SetResult(from photo in flickrResult.Result
                                          select photo.PhotoId));

the callback above wasn't running because at another point I was waiting for task completion, however the callback was to be marshalled to the calling thread, the same thread I have blocked.  *facepalm*.

 It does however appear that with concurrent calls to PhotosGetInfoAsync That we run into an issue where only one will get called back, are you missing a closure over an anonymous callback?

Coordinator
Jul 9, 2011 at 2:04 PM

That's great news. So nothing to do with the library then?

Cool.