1

I have a method that makes a list of all the Songs in the Media Library. The method has 2 aspects it either returns the SongsCollection from the MediaLibrary or returns a list of custom objects.

public static Task<object> GetSongList(bool lib = true, bool albumArt = true) { MediaLibrary mediaLib = new MediaLibrary(); var songs = mediaLib.Songs; if (lib) { return songs; } else { var list = new List<MusicTitle>(); foreach (var song in songs) { list.Add(new MusicTitle() { Artist = song.Artist.Name, Title = song.Name, Duration = (new DateTime(song.Duration.Ticks)).ToString("mm:ss"), Album = song.Album.Name, Art = albumArt ? GetAlbumArt(song, 100) : null }); } return list; } } 

MusicTitle is the custom class with some properties. since this return 2 types of results i set the return type as object and cast the result appropriately. This holds up the UI for a bit so i need this to be async. So as the methods shows i added Task<object> to the method signature and when i do that return songs; and return lists; gives compile following compile errors.

Cannot implicitly convert type 'Microsoft.Xna.Framework.Media.SongCollection' to 'System.Threading.Tasks.Task<object>' Cannot implicitly convert type 'System.Collections.Generic.List<KVKWindowsPhoneHelper.Core.MediaLibrary.MusicTitle>' to 'System.Threading.Tasks.Task<object>' 

What should i do? I tried casting the return types to object but did not work. How can i make this method async?

EDIT

The Following code is in side the Page's OnNavigatedTo() method This throws the UnauthorizedAccessException

protected async override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); // Set Song List List<AlphaKeyGroup<MusicTitle>> songList = await Task.Run(() => AlphaKeyGroup<MusicTitle>.CreateGroups(ListHelper.GetSongList(false, false) as List<MusicTitle>, Thread.CurrentThread.CurrentUICulture, (MusicTitle s) => { return s.Title; }, true)); listSongs.ItemsSource = songList; // Set Artist List List<AlphaKeyGroup<MusicArtist>> artistList = await Task.Run(() => AlphaKeyGroup<MusicArtist>.CreateGroups(ListHelper.GetArtistList(false) as List<MusicArtist>, Thread.CurrentThread.CurrentUICulture, (MusicArtist ar) => { return ar.Artist; }, true)); listArtist.ItemsSource = artistList; // Set Album List List<AlphaKeyGroup<MusicAlbum>> albumList = await Task.Run(() => AlphaKeyGroup<MusicAlbum>.CreateGroups(ListHelper.GetAlbumList(false, true) as List<MusicAlbum>, Thread.CurrentThread.CurrentUICulture, (MusicAlbum al) => { return al.Album; }, true)); listAlbums.ItemsSource = albumList; // Set Genre List List<AlphaKeyGroup<MusicGenre>> genreList = await Task.Run(() => AlphaKeyGroup<MusicGenre>.CreateGroups(ListHelper.GetGenreList(false) as List<MusicGenre>, Thread.CurrentThread.CurrentUICulture, (MusicGenre g) => { return g.Genre; }, true)); listGenres.ItemsSource = genreList; // Set PlayList List<AlphaKeyGroup<MusicPlaylist>> playList = await Task.Run(() => AlphaKeyGroup<MusicPlaylist>.CreateGroups(ListHelper.GetPlayList(false) as List<MusicPlaylist>, Thread.CurrentThread.CurrentUICulture, (MusicPlaylist pl) => { return pl.Playlist; }, true)); listPlaylist.ItemsSource = playList; } 

EDIT 2

In my Phone there are 233 songs, The exception is thrown at a method in a ListHelper class i wrote that includes all the methods to get the Songs, Albums, Playlist, Genres and Artists. The method that throws the exception is the method where i get the Album Art for the Album. This is the Method.

public static BitmapImage GetAlbumArt(Song song, int size = 100 ) { BitmapImage img = new BitmapImage(); // EXCEPTION IS THROWN HERE img.DecodePixelHeight = size; img.DecodePixelWidth = size; if (song.Album.HasArt) { img.SetSource(song.Album.GetAlbumArt()); } else { img.UriSource = new Uri("/Images/cover.png", UriKind.Relative); } return img; } 
3
  • 1
    Where do you perform an asynchronous operation? Commented Aug 2, 2014 at 14:15
  • Within the method there are no async operations, my objective is to create a async method so the creating of the list wont hold up the UI. I'm not sure i did the rigth thing here. Commented Aug 2, 2014 at 14:17
  • 2
    Run body of your method in Task.Run() and it will be queued in thread pool Commented Aug 2, 2014 at 14:24

1 Answer 1

1

Your method isn't doing any asynchronous work, hence there is no reason to make it return a Task. Instead, if you want to keep your UI responsive, wrap it inside a Task.Run which will queue it up on a ThreadPool thread:

public static object GetSongList(bool lib = true, bool albumArt = true) { MediaLibrary mediaLib = new MediaLibrary(); var songs = mediaLib.Songs; if (lib) { return songs; } else { var list = new List<MusicTitle>(); foreach (var song in songs) { list.Add(new MusicTitle() { Artist = song.Artist.Name, Title = song.Name, Duration = (new DateTime(song.Duration.Ticks)).ToString("mm:ss"), Album = song.Album.Name, Art = albumArt ? GetAlbumArt(song, 100) : null }); } return list; } } 

And use it inside a Task.Run:

var obj = await Task.Run(() => GetSongList()); 

As an unrelated side note, i would advise you to see if you might be able to create a common base class / interface as a return type instead of object, for type safety.

Sign up to request clarification or add additional context in comments.

10 Comments

Thanks, This works. UI is not held no more. But when this runs a uNauthorizedAccessException is thrown with additional information that includes Invalid cross-thread access message.. What should i do?
Hmm, are you accessing any UI elements inside this method?
You cant set the ItemSource inside a threadpool thread. Use Deployment.Current.Dispatcher.Invoke and set itemsource inside it
Using Dispatcher.BeginInvoke doesn't solve my problem. It still holds the UI till the lists are populated.
Thanks a lot. I will look in to it. :) I'll comment if i need help. Thanks
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.