Browse Source

a few more async optimizations

LukePulverenti Luke Pulverenti luke pulverenti 13 years ago
parent
commit
fbf8cc833c
37 changed files with 245 additions and 307 deletions
  1. 7 7
      MediaBrowser.Api/ApiService.cs
  2. 7 10
      MediaBrowser.Api/HttpHandlers/BaseMediaHandler.cs
  3. 3 3
      MediaBrowser.Api/HttpHandlers/GenreHandler.cs
  4. 3 3
      MediaBrowser.Api/HttpHandlers/GenresHandler.cs
  5. 13 13
      MediaBrowser.Api/HttpHandlers/ImageHandler.cs
  6. 2 2
      MediaBrowser.Api/HttpHandlers/ItemHandler.cs
  7. 3 3
      MediaBrowser.Api/HttpHandlers/ItemListHandler.cs
  8. 3 3
      MediaBrowser.Api/HttpHandlers/PersonHandler.cs
  9. 4 5
      MediaBrowser.Api/HttpHandlers/PluginConfigurationHandler.cs
  10. 14 17
      MediaBrowser.Api/HttpHandlers/PluginsHandler.cs
  11. 3 3
      MediaBrowser.Api/HttpHandlers/StudioHandler.cs
  12. 3 3
      MediaBrowser.Api/HttpHandlers/StudiosHandler.cs
  13. 1 4
      MediaBrowser.Api/HttpHandlers/UsersHandler.cs
  14. 3 3
      MediaBrowser.Api/HttpHandlers/YearHandler.cs
  15. 3 3
      MediaBrowser.Api/HttpHandlers/YearsHandler.cs
  16. 2 2
      MediaBrowser.Api/Plugin.cs
  17. 16 16
      MediaBrowser.ApiInteraction/ApiClient.cs
  18. 2 33
      MediaBrowser.Common/Net/Handlers/BaseEmbeddedResourceHandler.cs
  19. 7 7
      MediaBrowser.Common/Net/Handlers/BaseHandler.cs
  20. 4 7
      MediaBrowser.Common/Net/Handlers/BaseJsonHandler.cs
  21. 26 29
      MediaBrowser.Common/Net/Handlers/StaticFileHandler.cs
  22. 4 6
      MediaBrowser.Common/UI/BaseApplication.cs
  23. 9 13
      MediaBrowser.Controller/FFMpeg/FFProbe.cs
  24. 3 3
      MediaBrowser.Controller/IO/DirectoryWatchers.cs
  25. 16 21
      MediaBrowser.Controller/Kernel.cs
  26. 23 31
      MediaBrowser.Controller/Library/ItemController.cs
  27. 10 4
      MediaBrowser.Controller/Providers/AudioInfoProvider.cs
  28. 1 1
      MediaBrowser.Controller/Providers/BaseMetadataProvider.cs
  29. 4 2
      MediaBrowser.Controller/Providers/FolderProviderFromXml.cs
  30. 14 15
      MediaBrowser.Controller/Providers/ImageFromMediaLocationProvider.cs
  31. 3 7
      MediaBrowser.Controller/Providers/LocalTrailerProvider.cs
  32. 7 4
      MediaBrowser.Controller/Providers/VideoInfoProvider.cs
  33. 0 2
      MediaBrowser.Controller/Xml/BaseItemXmlParser.cs
  34. 4 2
      MediaBrowser.Movies/Providers/MovieProviderFromXml.cs
  35. 2 3
      MediaBrowser.TV/Providers/EpisodeImageFromMediaLocationProvider.cs
  36. 12 15
      MediaBrowser.TV/Providers/EpisodeProviderFromXml.cs
  37. 4 2
      MediaBrowser.TV/Providers/SeriesProviderFromXml.cs

+ 7 - 7
MediaBrowser.Api/ApiService.cs

@@ -81,16 +81,16 @@ namespace MediaBrowser.Api
 
             dto.UserData = item.GetUserData(user);
 
-            await AttachStudios(dto, item);
+            await AttachStudios(dto, item).ConfigureAwait(false);
 
             if (includeChildren)
             {
-                await AttachChildren(dto, item, user);
+                await AttachChildren(dto, item, user).ConfigureAwait(false);
             }
 
             if (includePeople)
             {
-                await AttachPeople(dto, item);
+                await AttachPeople(dto, item).ConfigureAwait(false);
             }
 
             Folder folder = item as Folder;
@@ -125,7 +125,7 @@ namespace MediaBrowser.Api
             // Attach Studios by transforming them into BaseItemStudio (DTO)
             if (item.Studios != null)
             {
-                IEnumerable<Studio> entities = await Task.WhenAll<Studio>(item.Studios.Select(c => Kernel.Instance.ItemController.GetStudio(c)));
+                IEnumerable<Studio> entities = await Task.WhenAll<Studio>(item.Studios.Select(c => Kernel.Instance.ItemController.GetStudio(c))).ConfigureAwait(false);
 
                 dto.Studios = item.Studios.Select(s =>
                 {
@@ -153,12 +153,12 @@ namespace MediaBrowser.Api
             {
                 IEnumerable<BaseItem> children = folder.GetParentalAllowedChildren(user);
 
-                dto.Children = await Task.WhenAll<DTOBaseItem>(children.Select(c => GetDTOBaseItem(c, user, false, false)));
+                dto.Children = await Task.WhenAll<DTOBaseItem>(children.Select(c => GetDTOBaseItem(c, user, false, false))).ConfigureAwait(false);
             }
 
             if (item.LocalTrailers != null && item.LocalTrailers.Any())
             {
-                dto.LocalTrailers = await Task.WhenAll<DTOBaseItem>(item.LocalTrailers.Select(c => GetDTOBaseItem(c, user, false, false)));
+                dto.LocalTrailers = await Task.WhenAll<DTOBaseItem>(item.LocalTrailers.Select(c => GetDTOBaseItem(c, user, false, false))).ConfigureAwait(false);
             }
         }
 
@@ -167,7 +167,7 @@ namespace MediaBrowser.Api
             // Attach People by transforming them into BaseItemPerson (DTO)
             if (item.People != null)
             {
-                IEnumerable<Person> entities = await Task.WhenAll<Person>(item.People.Select(c => Kernel.Instance.ItemController.GetPerson(c.Name)));
+                IEnumerable<Person> entities = await Task.WhenAll<Person>(item.People.Select(c => Kernel.Instance.ItemController.GetPerson(c.Name))).ConfigureAwait(false);
 
                 dto.People = item.People.Select(p =>
                 {

+ 7 - 10
MediaBrowser.Api/HttpHandlers/BaseMediaHandler.cs

@@ -92,10 +92,7 @@ namespace MediaBrowser.Api.HttpHandlers
 
         public override Task<string> GetContentType()
         {
-            return Task.Run(() =>
-            {
-                return MimeTypes.GetMimeType("." + GetConversionOutputFormat());
-            });
+            return Task.FromResult<string>(MimeTypes.GetMimeType("." + GetConversionOutputFormat()));
         }
 
         public override bool ShouldCompressResponse(string contentType)
@@ -103,17 +100,17 @@ namespace MediaBrowser.Api.HttpHandlers
             return false;
         }
 
-        public override async Task ProcessRequest(HttpListenerContext ctx)
+        public override Task ProcessRequest(HttpListenerContext ctx)
         {
             HttpListenerContext = ctx;
 
             if (!RequiresConversion())
             {
-                await new StaticFileHandler() { Path = LibraryItem.Path }.ProcessRequest(ctx);
+                return new StaticFileHandler() { Path = LibraryItem.Path }.ProcessRequest(ctx);
             }
             else
             {
-                await base.ProcessRequest(ctx);
+                return base.ProcessRequest(ctx);
             }
         }
 
@@ -180,15 +177,15 @@ namespace MediaBrowser.Api.HttpHandlers
                 // If we ever decide to disable the ffmpeg log then you must uncomment the below line.
                 //process.BeginErrorReadLine();
 
-                Task debugLogTask = Task.Run(async () => { await process.StandardError.BaseStream.CopyToAsync(logStream); });
+                Task debugLogTask = process.StandardError.BaseStream.CopyToAsync(logStream);
 
-                await process.StandardOutput.BaseStream.CopyToAsync(stream);
+                await process.StandardOutput.BaseStream.CopyToAsync(stream).ConfigureAwait(false);
 
                 process.WaitForExit();
 
                 Logger.LogInfo("FFMpeg exited with code " + process.ExitCode);
 
-                await debugLogTask;
+                await debugLogTask.ConfigureAwait(false);
             }
             catch (Exception ex)
             {

+ 3 - 3
MediaBrowser.Api/HttpHandlers/GenreHandler.cs

@@ -14,7 +14,7 @@ namespace MediaBrowser.Api.HttpHandlers
     /// </summary>
     public class GenreHandler : BaseJsonHandler<IBNItem<Genre>>
     {
-        protected override async Task<IBNItem<Genre>> GetObjectToSerialize()
+        protected override Task<IBNItem<Genre>> GetObjectToSerialize()
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
             Guid userId = Guid.Parse(QueryString["userid"]);
@@ -22,7 +22,7 @@ namespace MediaBrowser.Api.HttpHandlers
 
             string name = QueryString["name"];
 
-            return await GetGenre(parent, user, name);
+            return GetGenre(parent, user, name);
         }
 
         /// <summary>
@@ -46,7 +46,7 @@ namespace MediaBrowser.Api.HttpHandlers
             // Get the original entity so that we can also supply the PrimaryImagePath
             return new IBNItem<Genre>()
             {
-                Item = await Kernel.Instance.ItemController.GetGenre(name),
+                Item = await Kernel.Instance.ItemController.GetGenre(name).ConfigureAwait(false),
                 BaseItemCount = count
             };
         }

+ 3 - 3
MediaBrowser.Api/HttpHandlers/GenresHandler.cs

@@ -11,13 +11,13 @@ namespace MediaBrowser.Api.HttpHandlers
 {
     public class GenresHandler : BaseJsonHandler<IEnumerable<IBNItem<Genre>>>
     {
-        protected override async Task<IEnumerable<IBNItem<Genre>>> GetObjectToSerialize()
+        protected override Task<IEnumerable<IBNItem<Genre>>> GetObjectToSerialize()
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
             Guid userId = Guid.Parse(QueryString["userid"]);
             User user = Kernel.Instance.Users.First(u => u.Id == userId);
 
-            return await GetAllGenres(parent, user);
+            return GetAllGenres(parent, user);
         }
 
         /// <summary>
@@ -53,7 +53,7 @@ namespace MediaBrowser.Api.HttpHandlers
                 }
             }
 
-            IEnumerable<Genre> entities = await Task.WhenAll<Genre>(data.Keys.Select(key => { return Kernel.Instance.ItemController.GetGenre(key); }));
+            IEnumerable<Genre> entities = await Task.WhenAll<Genre>(data.Keys.Select(key => { return Kernel.Instance.ItemController.GetGenre(key); })).ConfigureAwait(false);
 
             return entities.Select(e => new IBNItem<Genre>() { Item = e, BaseItemCount = data[e.Name] });
         }

+ 13 - 13
MediaBrowser.Api/HttpHandlers/ImageHandler.cs

@@ -29,28 +29,28 @@ namespace MediaBrowser.Api.HttpHandlers
 
             if (!string.IsNullOrEmpty(personName))
             {
-                return (await Kernel.Instance.ItemController.GetPerson(personName)).PrimaryImagePath;
+                return (await Kernel.Instance.ItemController.GetPerson(personName).ConfigureAwait(false)).PrimaryImagePath;
             }
 
             string genreName = QueryString["genre"];
 
             if (!string.IsNullOrEmpty(genreName))
             {
-                return (await Kernel.Instance.ItemController.GetGenre(genreName)).PrimaryImagePath;
+                return (await Kernel.Instance.ItemController.GetGenre(genreName).ConfigureAwait(false)).PrimaryImagePath;
             }
 
             string year = QueryString["year"];
 
             if (!string.IsNullOrEmpty(year))
             {
-                return (await Kernel.Instance.ItemController.GetYear(int.Parse(year))).PrimaryImagePath;
+                return (await Kernel.Instance.ItemController.GetYear(int.Parse(year)).ConfigureAwait(false)).PrimaryImagePath;
             }
 
             string studio = QueryString["studio"];
 
             if (!string.IsNullOrEmpty(studio))
             {
-                return (await Kernel.Instance.ItemController.GetStudio(studio)).PrimaryImagePath;
+                return (await Kernel.Instance.ItemController.GetStudio(studio).ConfigureAwait(false)).PrimaryImagePath;
             }
             
             BaseItem item = ApiService.GetItemById(QueryString["id"]);
@@ -64,7 +64,7 @@ namespace MediaBrowser.Api.HttpHandlers
         private Stream _SourceStream = null;
         private async Task<Stream> GetSourceStream()
         {
-            await EnsureSourceStream();
+            await EnsureSourceStream().ConfigureAwait(false);
             return _SourceStream;
         }
 
@@ -75,7 +75,7 @@ namespace MediaBrowser.Api.HttpHandlers
             {
                 try
                 {
-                    _SourceStream = File.OpenRead(await GetImagePath());
+                    _SourceStream = File.OpenRead(await GetImagePath().ConfigureAwait(false));
                 }
                 catch (FileNotFoundException ex)
                 {
@@ -101,14 +101,14 @@ namespace MediaBrowser.Api.HttpHandlers
 
         public async override Task<string> GetContentType()
         {
-            await EnsureSourceStream();
+            await EnsureSourceStream().ConfigureAwait(false);
 
-            if (await GetSourceStream() == null)
+            if (await GetSourceStream().ConfigureAwait(false) == null)
             {
                 return null;
             }
 
-            return MimeTypes.GetMimeType(await GetImagePath());
+            return MimeTypes.GetMimeType(await GetImagePath().ConfigureAwait(false));
         }
 
         public override TimeSpan CacheDuration
@@ -121,14 +121,14 @@ namespace MediaBrowser.Api.HttpHandlers
 
         protected async override Task<DateTime?> GetLastDateModified()
         {
-            await EnsureSourceStream();
+            await EnsureSourceStream().ConfigureAwait(false);
 
-            if (await GetSourceStream() == null)
+            if (await GetSourceStream().ConfigureAwait(false) == null)
             {
                 return null;
             }
 
-            return File.GetLastWriteTime(await GetImagePath());
+            return File.GetLastWriteTime(await GetImagePath().ConfigureAwait(false));
         }
 
         private int? Height
@@ -223,7 +223,7 @@ namespace MediaBrowser.Api.HttpHandlers
 
         protected override async Task WriteResponseToOutputStream(Stream stream)
         {
-            ImageProcessor.ProcessImage(await GetSourceStream(), stream, Width, Height, MaxWidth, MaxHeight, Quality);
+            ImageProcessor.ProcessImage(await GetSourceStream().ConfigureAwait(false), stream, Width, Height, MaxWidth, MaxHeight, Quality);
         }
 
         private string GetImagePathFromTypes(BaseItem item, ImageType imageType, int imageIndex)

+ 2 - 2
MediaBrowser.Api/HttpHandlers/ItemHandler.cs

@@ -10,7 +10,7 @@ namespace MediaBrowser.Api.HttpHandlers
 {
     public class ItemHandler : BaseJsonHandler<DTOBaseItem>
     {
-        protected async override Task<DTOBaseItem> GetObjectToSerialize()
+        protected override Task<DTOBaseItem> GetObjectToSerialize()
         {
             Guid userId = Guid.Parse(QueryString["userid"]);
             User user = Kernel.Instance.Users.First(u => u.Id == userId);
@@ -22,7 +22,7 @@ namespace MediaBrowser.Api.HttpHandlers
                 return null;
             }
 
-            return await ApiService.GetDTOBaseItem(item, user);
+            return ApiService.GetDTOBaseItem(item, user);
         }
 
         protected virtual BaseItem ItemToSerialize

+ 3 - 3
MediaBrowser.Api/HttpHandlers/ItemListHandler.cs

@@ -9,13 +9,13 @@ using MediaBrowser.Model.Entities;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
-    public class ItemListHandler : BaseJsonHandler<IEnumerable<DTOBaseItem>>
+    public class ItemListHandler : BaseJsonHandler<DTOBaseItem[]>
     {
-        protected override async Task<IEnumerable<DTOBaseItem>> GetObjectToSerialize()
+        protected override Task<DTOBaseItem[]> GetObjectToSerialize()
         {
             User user = Kernel.Instance.Users.First(u => u.Id == UserId);
 
-            return await Task.WhenAll<DTOBaseItem>(ItemsToSerialize.Select(i =>
+            return Task.WhenAll<DTOBaseItem>(ItemsToSerialize.Select(i =>
             {
                 return ApiService.GetDTOBaseItem(i, user, includeChildren: false, includePeople: false);
             }));

+ 3 - 3
MediaBrowser.Api/HttpHandlers/PersonHandler.cs

@@ -14,7 +14,7 @@ namespace MediaBrowser.Api.HttpHandlers
     /// </summary>
     public class PersonHandler : BaseJsonHandler<IBNItem<Person>>
     {
-        protected async override Task<IBNItem<Person>> GetObjectToSerialize()
+        protected override Task<IBNItem<Person>> GetObjectToSerialize()
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
             Guid userId = Guid.Parse(QueryString["userid"]);
@@ -22,7 +22,7 @@ namespace MediaBrowser.Api.HttpHandlers
 
             string name = QueryString["name"];
 
-            return await GetPerson(parent, user, name);
+            return GetPerson(parent, user, name);
         }
 
         /// <summary>
@@ -46,7 +46,7 @@ namespace MediaBrowser.Api.HttpHandlers
             // Get the original entity so that we can also supply the PrimaryImagePath
             return new IBNItem<Person>()
             {
-                Item = await Kernel.Instance.ItemController.GetPerson(name),
+                Item = await Kernel.Instance.ItemController.GetPerson(name).ConfigureAwait(false),
                 BaseItemCount = count
             };
         }

+ 4 - 5
MediaBrowser.Api/HttpHandlers/PluginConfigurationHandler.cs

@@ -11,12 +11,11 @@ namespace MediaBrowser.Api.HttpHandlers
     {
         protected override Task<BasePluginConfiguration> GetObjectToSerialize()
         {
-            return Task.Run(() =>
-            {
-                string pluginName = QueryString["name"];
+            string pluginName = QueryString["name"];
 
-                return Kernel.Instance.Plugins.First(p => p.Name.Equals(pluginName, StringComparison.OrdinalIgnoreCase)).Configuration;
-            });
+            BasePluginConfiguration config = Kernel.Instance.Plugins.First(p => p.Name.Equals(pluginName, StringComparison.OrdinalIgnoreCase)).Configuration;
+
+            return Task.FromResult<BasePluginConfiguration>(config);
         }
     }
 }

+ 14 - 17
MediaBrowser.Api/HttpHandlers/PluginsHandler.cs

@@ -14,27 +14,24 @@ namespace MediaBrowser.Api.HttpHandlers
     {
         protected override Task<IEnumerable<PluginInfo>> GetObjectToSerialize()
         {
-            return Task.Run(() =>
+            var plugins = Kernel.Instance.Plugins.Select(p =>
             {
-                var plugins = Kernel.Instance.Plugins.Select(p =>
+                return new PluginInfo()
                 {
-                    return new PluginInfo()
-                    {
-                        Path = p.Path,
-                        Name = p.Name,
-                        Enabled = p.Enabled,
-                        DownloadToUI = p.DownloadToUI,
-                        Version = p.Version
-                    };
-                });
+                    Path = p.Path,
+                    Name = p.Name,
+                    Enabled = p.Enabled,
+                    DownloadToUI = p.DownloadToUI,
+                    Version = p.Version
+                };
+            });
 
-                if (QueryString["uionly"] == "1")
-                {
-                    plugins = plugins.Where(p => p.DownloadToUI);
-                }
+            if (QueryString["uionly"] == "1")
+            {
+                plugins = plugins.Where(p => p.DownloadToUI);
+            }
 
-                return plugins;
-            });
+            return Task.FromResult<IEnumerable<PluginInfo>>(plugins);
         }
     }
 }

+ 3 - 3
MediaBrowser.Api/HttpHandlers/StudioHandler.cs

@@ -14,7 +14,7 @@ namespace MediaBrowser.Api.HttpHandlers
     /// </summary>
     public class StudioHandler : BaseJsonHandler<IBNItem<Studio>>
     {
-        protected async override Task<IBNItem<Studio>> GetObjectToSerialize()
+        protected override Task<IBNItem<Studio>> GetObjectToSerialize()
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
             Guid userId = Guid.Parse(QueryString["userid"]);
@@ -22,7 +22,7 @@ namespace MediaBrowser.Api.HttpHandlers
 
             string name = QueryString["name"];
 
-            return await GetStudio(parent, user, name);
+            return GetStudio(parent, user, name);
         }
 
         /// <summary>
@@ -46,7 +46,7 @@ namespace MediaBrowser.Api.HttpHandlers
             // Get the original entity so that we can also supply the PrimaryImagePath
             return new IBNItem<Studio>()
             {
-                Item = await Kernel.Instance.ItemController.GetStudio(name),
+                Item = await Kernel.Instance.ItemController.GetStudio(name).ConfigureAwait(false),
                 BaseItemCount = count
             };
         }

+ 3 - 3
MediaBrowser.Api/HttpHandlers/StudiosHandler.cs

@@ -11,13 +11,13 @@ namespace MediaBrowser.Api.HttpHandlers
 {
     public class StudiosHandler : BaseJsonHandler<IEnumerable<IBNItem<Studio>>>
     {
-        protected override async Task<IEnumerable<IBNItem<Studio>>> GetObjectToSerialize()
+        protected override Task<IEnumerable<IBNItem<Studio>>> GetObjectToSerialize()
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
             Guid userId = Guid.Parse(QueryString["userid"]);
             User user = Kernel.Instance.Users.First(u => u.Id == userId);
 
-            return await GetAllStudios(parent, user);
+            return GetAllStudios(parent, user);
         }
 
         /// <summary>
@@ -53,7 +53,7 @@ namespace MediaBrowser.Api.HttpHandlers
                 }
             }
 
-            IEnumerable<Studio> entities = await Task.WhenAll<Studio>(data.Keys.Select(key => { return Kernel.Instance.ItemController.GetStudio(key); }));
+            IEnumerable<Studio> entities = await Task.WhenAll<Studio>(data.Keys.Select(key => { return Kernel.Instance.ItemController.GetStudio(key); })).ConfigureAwait(false);
 
             return entities.Select(e => new IBNItem<Studio>() { Item = e, BaseItemCount = data[e.Name] });
         }

+ 1 - 4
MediaBrowser.Api/HttpHandlers/UsersHandler.cs

@@ -10,10 +10,7 @@ namespace MediaBrowser.Api.HttpHandlers
     {
         protected override Task<IEnumerable<User>> GetObjectToSerialize()
         {
-            return Task.Run(() =>
-            {
-                return Kernel.Instance.Users;
-            });
+            return Task.FromResult<IEnumerable<User>>(Kernel.Instance.Users);
         }
     }
 }

+ 3 - 3
MediaBrowser.Api/HttpHandlers/YearHandler.cs

@@ -14,7 +14,7 @@ namespace MediaBrowser.Api.HttpHandlers
     /// </summary>
     public class YearHandler : BaseJsonHandler<IBNItem<Year>>
     {
-        protected override async Task<IBNItem<Year>> GetObjectToSerialize()
+        protected override Task<IBNItem<Year>> GetObjectToSerialize()
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
             Guid userId = Guid.Parse(QueryString["userid"]);
@@ -22,7 +22,7 @@ namespace MediaBrowser.Api.HttpHandlers
 
             string year = QueryString["year"];
 
-            return await GetYear(parent, user, int.Parse(year));
+            return GetYear(parent, user, int.Parse(year));
         }
 
         /// <summary>
@@ -46,7 +46,7 @@ namespace MediaBrowser.Api.HttpHandlers
             // Get the original entity so that we can also supply the PrimaryImagePath
             return new IBNItem<Year>()
             {
-                Item = await Kernel.Instance.ItemController.GetYear(year),
+                Item = await Kernel.Instance.ItemController.GetYear(year).ConfigureAwait(false),
                 BaseItemCount = count
             };
         }

+ 3 - 3
MediaBrowser.Api/HttpHandlers/YearsHandler.cs

@@ -11,13 +11,13 @@ namespace MediaBrowser.Api.HttpHandlers
 {
     public class YearsHandler : BaseJsonHandler<IEnumerable<IBNItem<Year>>>
     {
-        protected override async Task<IEnumerable<IBNItem<Year>>> GetObjectToSerialize()
+        protected override Task<IEnumerable<IBNItem<Year>>> GetObjectToSerialize()
         {
             Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
             Guid userId = Guid.Parse(QueryString["userid"]);
             User user = Kernel.Instance.Users.First(u => u.Id == userId);
 
-            return await GetAllYears(parent, user);
+            return GetAllYears(parent, user);
         }
 
         /// <summary>
@@ -50,7 +50,7 @@ namespace MediaBrowser.Api.HttpHandlers
                 }
             }
 
-            IEnumerable<Year> entities = await Task.WhenAll<Year>(data.Keys.Select(key => { return Kernel.Instance.ItemController.GetYear(key); }));
+            IEnumerable<Year> entities = await Task.WhenAll<Year>(data.Keys.Select(key => { return Kernel.Instance.ItemController.GetYear(key); })).ConfigureAwait(false);
 
             return entities.Select(e => new IBNItem<Year>() { Item = e, BaseItemCount = data[int.Parse(e.Name)] });
         }

+ 2 - 2
MediaBrowser.Api/Plugin.cs

@@ -22,13 +22,13 @@ namespace MediaBrowser.Api
         {
             var httpServer = Kernel.Instance.HttpServer;
 
-            httpServer.Where(ctx => ctx.Request.Url.LocalPath.IndexOf("/api/", StringComparison.OrdinalIgnoreCase) != -1).Subscribe(async (ctx) =>
+            httpServer.Where(ctx => ctx.Request.Url.LocalPath.IndexOf("/api/", StringComparison.OrdinalIgnoreCase) != -1).Subscribe((ctx) =>
             {
                 BaseHandler handler = GetHandler(ctx);
 
                 if (handler != null)
                 {
-                    await handler.ProcessRequest(ctx);
+                    handler.ProcessRequest(ctx);
                 }
             });
         }

+ 16 - 16
MediaBrowser.ApiInteraction/ApiClient.cs

@@ -152,9 +152,9 @@ namespace MediaBrowser.ApiInteraction
         /// <summary>
         /// Gets an image stream based on a url
         /// </summary>
-        public async Task<Stream> GetImageStreamAsync(string url)
+        public Task<Stream> GetImageStreamAsync(string url)
         {
-            return await HttpClient.GetStreamAsync(url);
+            return HttpClient.GetStreamAsync(url);
         }
 
         /// <summary>
@@ -169,7 +169,7 @@ namespace MediaBrowser.ApiInteraction
                 url += "&id=" + id.ToString();
             }
 
-            using (Stream stream = await HttpClient.GetStreamAsync(url))
+            using (Stream stream = await HttpClient.GetStreamAsync(url).ConfigureAwait(false))
             {
                 return JsonSerializer.DeserializeFromStream<DTOBaseItem>(stream);
             }
@@ -182,7 +182,7 @@ namespace MediaBrowser.ApiInteraction
         {
             string url = ApiUrl + "/users";
 
-            using (Stream stream = await HttpClient.GetStreamAsync(url))
+            using (Stream stream = await HttpClient.GetStreamAsync(url).ConfigureAwait(false))
             {
                 return JsonSerializer.DeserializeFromStream<IEnumerable<User>>(stream);
             }
@@ -195,7 +195,7 @@ namespace MediaBrowser.ApiInteraction
         {
             string url = ApiUrl + "/genres?userId=" + userId.ToString();
 
-            using (Stream stream = await HttpClient.GetStreamAsync(url))
+            using (Stream stream = await HttpClient.GetStreamAsync(url).ConfigureAwait(false))
             {
                 return JsonSerializer.DeserializeFromStream<IEnumerable<IBNItem<Genre>>>(stream);
             }
@@ -208,7 +208,7 @@ namespace MediaBrowser.ApiInteraction
         {
             string url = ApiUrl + "/years?userId=" + userId.ToString();
 
-            using (Stream stream = await HttpClient.GetStreamAsync(url))
+            using (Stream stream = await HttpClient.GetStreamAsync(url).ConfigureAwait(false))
             {
                 return JsonSerializer.DeserializeFromStream<IEnumerable<IBNItem<Year>>>(stream);
             }
@@ -221,7 +221,7 @@ namespace MediaBrowser.ApiInteraction
         {
             string url = ApiUrl + "/itemlist?listtype=itemswithyear&userId=" + userId.ToString() + "&name=" + name;
 
-            using (Stream stream = await HttpClient.GetStreamAsync(url))
+            using (Stream stream = await HttpClient.GetStreamAsync(url).ConfigureAwait(false))
             {
                 return JsonSerializer.DeserializeFromStream<IEnumerable<DTOBaseItem>>(stream);
             }
@@ -234,7 +234,7 @@ namespace MediaBrowser.ApiInteraction
         {
             string url = ApiUrl + "/itemlist?listtype=itemswithgenre&userId=" + userId.ToString() + "&name=" + name;
 
-            using (Stream stream = await HttpClient.GetStreamAsync(url))
+            using (Stream stream = await HttpClient.GetStreamAsync(url).ConfigureAwait(false))
             {
                 return JsonSerializer.DeserializeFromStream<IEnumerable<DTOBaseItem>>(stream);
             }
@@ -247,7 +247,7 @@ namespace MediaBrowser.ApiInteraction
         {
             string url = ApiUrl + "/itemlist?listtype=itemswithperson&userId=" + userId.ToString() + "&name=" + name;
 
-            using (Stream stream = await HttpClient.GetStreamAsync(url))
+            using (Stream stream = await HttpClient.GetStreamAsync(url).ConfigureAwait(false))
             {
                 return JsonSerializer.DeserializeFromStream<IEnumerable<DTOBaseItem>>(stream);
             }
@@ -262,7 +262,7 @@ namespace MediaBrowser.ApiInteraction
 
             url += "&persontype=" + personType;
 
-            using (Stream stream = await HttpClient.GetStreamAsync(url))
+            using (Stream stream = await HttpClient.GetStreamAsync(url).ConfigureAwait(false))
             {
                 return JsonSerializer.DeserializeFromStream<IEnumerable<DTOBaseItem>>(stream);
             }
@@ -275,7 +275,7 @@ namespace MediaBrowser.ApiInteraction
         {
             string url = ApiUrl + "/studios?userId=" + userId.ToString();
 
-            using (Stream stream = await HttpClient.GetStreamAsync(url))
+            using (Stream stream = await HttpClient.GetStreamAsync(url).ConfigureAwait(false))
             {
                 return JsonSerializer.DeserializeFromStream<IEnumerable<IBNItem<Studio>>>(stream);
             }
@@ -288,7 +288,7 @@ namespace MediaBrowser.ApiInteraction
         {
             string url = ApiUrl + "/itemlist?listtype=itemswithstudio&userId=" + userId.ToString() + "&name=" + name;
 
-            using (Stream stream = await HttpClient.GetStreamAsync(url))
+            using (Stream stream = await HttpClient.GetStreamAsync(url).ConfigureAwait(false))
             {
                 return JsonSerializer.DeserializeFromStream<IEnumerable<DTOBaseItem>>(stream);
             }
@@ -301,7 +301,7 @@ namespace MediaBrowser.ApiInteraction
         {
             string url = ApiUrl + "/studio?userId=" + userId.ToString() + "&name=" + name;
 
-            using (Stream stream = await HttpClient.GetStreamAsync(url))
+            using (Stream stream = await HttpClient.GetStreamAsync(url).ConfigureAwait(false))
             {
                 return JsonSerializer.DeserializeFromStream<IBNItem<Studio>>(stream);
             }
@@ -314,7 +314,7 @@ namespace MediaBrowser.ApiInteraction
         {
             string url = ApiUrl + "/genre?userId=" + userId.ToString() + "&name=" + name;
 
-            using (Stream stream = await HttpClient.GetStreamAsync(url))
+            using (Stream stream = await HttpClient.GetStreamAsync(url).ConfigureAwait(false))
             {
                 return JsonSerializer.DeserializeFromStream<IBNItem<Genre>>(stream);
             }
@@ -327,7 +327,7 @@ namespace MediaBrowser.ApiInteraction
         {
             string url = ApiUrl + "/person?userId=" + userId.ToString() + "&name=" + name;
 
-            using (Stream stream = await HttpClient.GetStreamAsync(url))
+            using (Stream stream = await HttpClient.GetStreamAsync(url).ConfigureAwait(false))
             {
                 return JsonSerializer.DeserializeFromStream<IBNItem<Person>>(stream);
             }
@@ -340,7 +340,7 @@ namespace MediaBrowser.ApiInteraction
         {
             string url = ApiUrl + "/year?userId=" + userId.ToString() + "&year=" + year;
 
-            using (Stream stream = await HttpClient.GetStreamAsync(url))
+            using (Stream stream = await HttpClient.GetStreamAsync(url).ConfigureAwait(false))
             {
                 return JsonSerializer.DeserializeFromStream<IBNItem<Year>>(stream);
             }

+ 2 - 33
MediaBrowser.Common/Net/Handlers/BaseEmbeddedResourceHandler.cs

@@ -1,5 +1,4 @@
-using System;
-using System.IO;
+using System.IO;
 using System.Threading.Tasks;
 
 namespace MediaBrowser.Common.Net.Handlers
@@ -16,37 +15,7 @@ namespace MediaBrowser.Common.Net.Handlers
 
         public override Task<string> GetContentType()
         {
-            return Task.Run(() =>
-            {
-                string extension = Path.GetExtension(ResourcePath);
-
-                if (extension.EndsWith("jpeg", StringComparison.OrdinalIgnoreCase) || extension.EndsWith("jpg", StringComparison.OrdinalIgnoreCase))
-                {
-                    return "image/jpeg";
-                }
-                else if (extension.EndsWith("png", StringComparison.OrdinalIgnoreCase))
-                {
-                    return "image/png";
-                }
-                else if (extension.EndsWith("ico", StringComparison.OrdinalIgnoreCase))
-                {
-                    return "image/ico";
-                }
-                else if (extension.EndsWith("js", StringComparison.OrdinalIgnoreCase))
-                {
-                    return "application/x-javascript";
-                }
-                else if (extension.EndsWith("css", StringComparison.OrdinalIgnoreCase))
-                {
-                    return "text/css";
-                }
-                else if (extension.EndsWith("html", StringComparison.OrdinalIgnoreCase))
-                {
-                    return "text/html; charset=utf-8";
-                }
-
-                return "text/plain; charset=utf-8";
-            });
+            return Task.FromResult<string>(MimeTypes.GetMimeType(ResourcePath));
         }
 
         protected override Task WriteResponseToOutputStream(Stream stream)

+ 7 - 7
MediaBrowser.Common/Net/Handlers/BaseHandler.cs

@@ -185,11 +185,11 @@ namespace MediaBrowser.Common.Net.Handlers
                 // When serving a range request, we need to return status code 206 to indicate a partial response body
                 StatusCode = SupportsByteRangeRequests && IsRangeRequest ? 206 : 200;
 
-                ctx.Response.ContentType = await GetContentType();
+                ctx.Response.ContentType = await GetContentType().ConfigureAwait(false);
 
                 TimeSpan cacheDuration = CacheDuration;
 
-                DateTime? lastDateModified = await GetLastDateModified();
+                DateTime? lastDateModified = await GetLastDateModified().ConfigureAwait(false);
 
                 if (ctx.Request.Headers.AllKeys.Contains("If-Modified-Since"))
                 {
@@ -205,13 +205,13 @@ namespace MediaBrowser.Common.Net.Handlers
                     }
                 }
 
-                await PrepareResponse();
+                await PrepareResponse().ConfigureAwait(false);
 
                 if (IsResponseValid)
                 {
                     bool compressResponse = ShouldCompressResponse(ctx.Response.ContentType) && ClientSupportsCompression;
 
-                    await ProcessUncachedRequest(ctx, compressResponse, cacheDuration, lastDateModified);
+                    await ProcessUncachedRequest(ctx, compressResponse, cacheDuration, lastDateModified).ConfigureAwait(false);
                 }
                 else
                 {
@@ -285,7 +285,7 @@ namespace MediaBrowser.Common.Net.Handlers
                     outputStream = CompressedStream;
                 }
 
-                await WriteResponseToOutputStream(outputStream);
+                await WriteResponseToOutputStream(outputStream).ConfigureAwait(false);
             }
             else
             {
@@ -307,7 +307,7 @@ namespace MediaBrowser.Common.Net.Handlers
         /// </summary>
         protected virtual Task PrepareResponse()
         {
-            return Task.Run(() => { });
+            return Task.FromResult<object>(null);
         }
 
         protected abstract Task WriteResponseToOutputStream(Stream stream);
@@ -359,7 +359,7 @@ namespace MediaBrowser.Common.Net.Handlers
         {
             DateTime? value = null;
 
-            return Task.Run<DateTime?>(() => { return value; });
+            return Task.FromResult<DateTime?>(value);
         }
 
         private bool IsResponseValid

+ 4 - 7
MediaBrowser.Common/Net/Handlers/BaseJsonHandler.cs

@@ -8,10 +8,7 @@ namespace MediaBrowser.Common.Net.Handlers
     {
         public override Task<string> GetContentType()
         {
-            return Task.Run(() =>
-            {
-                return MimeTypes.JsonMimeType;
-            });
+            return Task.FromResult<string>(MimeTypes.JsonMimeType);
         }
 
         private bool _ObjectToSerializeEnsured = false;
@@ -21,7 +18,7 @@ namespace MediaBrowser.Common.Net.Handlers
         {
             if (!_ObjectToSerializeEnsured)
             {
-                _ObjectToSerialize = await GetObjectToSerialize();
+                _ObjectToSerialize = await GetObjectToSerialize().ConfigureAwait(false);
 
                 if (_ObjectToSerialize == null)
                 {
@@ -34,9 +31,9 @@ namespace MediaBrowser.Common.Net.Handlers
 
         protected abstract Task<T> GetObjectToSerialize();
 
-        protected override async Task PrepareResponse()
+        protected override Task PrepareResponse()
         {
-            await EnsureObjectToSerialize();
+            return EnsureObjectToSerialize();
         }
 
         protected async override Task WriteResponseToOutputStream(Stream stream)

+ 26 - 29
MediaBrowser.Common/Net/Handlers/StaticFileHandler.cs

@@ -102,33 +102,30 @@ namespace MediaBrowser.Common.Net.Handlers
 
         protected override Task<DateTime?> GetLastDateModified()
         {
-            return Task.Run<DateTime?>(() =>
-            {
-                EnsureSourceStream();
+            DateTime? value = null;
 
-                if (SourceStream == null)
-                {
-                    return null;
-                }
+            EnsureSourceStream();
 
-                return File.GetLastWriteTime(Path);
-            });
+            if (SourceStream != null)
+            {
+                value = File.GetLastWriteTime(Path);
+            }
+
+            return Task.FromResult<DateTime?>(value);
         }
 
         public override Task<string> GetContentType()
         {
-            return Task.Run(() =>
-            {
-                return MimeTypes.GetMimeType(Path);
-            });
+            return Task.FromResult<string>(MimeTypes.GetMimeType(Path));
         }
 
         protected override Task PrepareResponse()
         {
-            return Task.Run(() => { EnsureSourceStream(); });
+            EnsureSourceStream();
+            return Task.FromResult<object>(null);
         }
 
-        protected async override Task WriteResponseToOutputStream(Stream stream)
+        protected override Task WriteResponseToOutputStream(Stream stream)
         {
             if (IsRangeRequest)
             {
@@ -137,22 +134,22 @@ namespace MediaBrowser.Common.Net.Handlers
                 // If the requested range is "0-" and we know the total length, we can optimize by avoiding having to buffer the content into memory
                 if (requestedRange.Value == null && TotalContentLength != null)
                 {
-                    await ServeCompleteRangeRequest(requestedRange, stream);
+                    return ServeCompleteRangeRequest(requestedRange, stream);
                 }
                 else if (TotalContentLength.HasValue)
                 {
                     // This will have to buffer a portion of the content into memory
-                    await ServePartialRangeRequestWithKnownTotalContentLength(requestedRange, stream);
+                    return ServePartialRangeRequestWithKnownTotalContentLength(requestedRange, stream);
                 }
                 else
                 {
                     // This will have to buffer the entire content into memory
-                    await ServePartialRangeRequestWithUnknownTotalContentLength(requestedRange, stream);
+                    return ServePartialRangeRequestWithUnknownTotalContentLength(requestedRange, stream);
                 }
             }
             else
             {
-                await SourceStream.CopyToAsync(stream);
+                return SourceStream.CopyToAsync(stream);
             }
         }
 
@@ -170,7 +167,7 @@ namespace MediaBrowser.Common.Net.Handlers
         /// Handles a range request of "bytes=0-"
         /// This will serve the complete content and add the content-range header
         /// </summary>
-        private async Task ServeCompleteRangeRequest(KeyValuePair<long, long?> requestedRange, Stream responseStream)
+        private Task ServeCompleteRangeRequest(KeyValuePair<long, long?> requestedRange, Stream responseStream)
         {
             long totalContentLength = TotalContentLength.Value;
 
@@ -187,7 +184,7 @@ namespace MediaBrowser.Common.Net.Handlers
                 SourceStream.Position = rangeStart;
             }
 
-            await SourceStream.CopyToAsync(responseStream);
+            return SourceStream.CopyToAsync(responseStream);
         }
 
         /// <summary>
@@ -196,7 +193,7 @@ namespace MediaBrowser.Common.Net.Handlers
         private async Task ServePartialRangeRequestWithUnknownTotalContentLength(KeyValuePair<long, long?> requestedRange, Stream responseStream)
         {
             // Read the entire stream so that we can determine the length
-            byte[] bytes = await ReadBytes(SourceStream, 0, null);
+            byte[] bytes = await ReadBytes(SourceStream, 0, null).ConfigureAwait(false);
 
             long totalContentLength = bytes.LongLength;
 
@@ -208,7 +205,7 @@ namespace MediaBrowser.Common.Net.Handlers
             HttpListenerContext.Response.ContentLength64 = rangeLength;
             HttpListenerContext.Response.Headers["Content-Range"] = string.Format("bytes {0}-{1}/{2}", rangeStart, rangeEnd, totalContentLength);
 
-            await responseStream.WriteAsync(bytes, Convert.ToInt32(rangeStart), Convert.ToInt32(rangeLength));
+            await responseStream.WriteAsync(bytes, Convert.ToInt32(rangeStart), Convert.ToInt32(rangeLength)).ConfigureAwait(false);
         }
 
         /// <summary>
@@ -222,14 +219,14 @@ namespace MediaBrowser.Common.Net.Handlers
             long rangeLength = 1 + rangeEnd - rangeStart;
 
             // Only read the bytes we need
-            byte[] bytes = await ReadBytes(SourceStream, Convert.ToInt32(rangeStart), Convert.ToInt32(rangeLength));
+            byte[] bytes = await ReadBytes(SourceStream, Convert.ToInt32(rangeStart), Convert.ToInt32(rangeLength)).ConfigureAwait(false);
 
             // Content-Length is the length of what we're serving, not the original content
             HttpListenerContext.Response.ContentLength64 = rangeLength;
 
             HttpListenerContext.Response.Headers["Content-Range"] = string.Format("bytes {0}-{1}/{2}", rangeStart, rangeEnd, totalContentLength);
 
-            await responseStream.WriteAsync(bytes, 0, Convert.ToInt32(rangeLength));
+            await responseStream.WriteAsync(bytes, 0, Convert.ToInt32(rangeLength)).ConfigureAwait(false);
         }
 
         /// <summary>
@@ -252,9 +249,9 @@ namespace MediaBrowser.Common.Net.Handlers
                 using (MemoryStream ms = new MemoryStream())
                 {
                     int read;
-                    while ((read = await input.ReadAsync(buffer, 0, buffer.Length)) > 0)
+                    while ((read = await input.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false)) > 0)
                     {
-                        await ms.WriteAsync(buffer, 0, read);
+                        await ms.WriteAsync(buffer, 0, read).ConfigureAwait(false);
                     }
                     return ms.ToArray();
                 }
@@ -265,9 +262,9 @@ namespace MediaBrowser.Common.Net.Handlers
 
                 using (MemoryStream ms = new MemoryStream())
                 {
-                    int read = await input.ReadAsync(buffer, 0, buffer.Length);
+                    int read = await input.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
 
-                    await ms.WriteAsync(buffer, 0, read);
+                    await ms.WriteAsync(buffer, 0, read).ConfigureAwait(false);
 
                     return ms.ToArray();
                 }

+ 4 - 6
MediaBrowser.Common/UI/BaseApplication.cs

@@ -17,15 +17,15 @@ namespace MediaBrowser.Common.UI
         protected abstract IKernel InstantiateKernel();
         protected abstract Window InstantiateMainWindow();
 
-        protected async override void OnStartup(StartupEventArgs e)
+        protected override void OnStartup(StartupEventArgs e)
         {
             // Without this the app will shutdown after the splash screen closes
             this.ShutdownMode = ShutdownMode.OnExplicitShutdown;
 
-            await LoadKernel().ConfigureAwait(false);
+            LoadKernel();
         }
 
-        private async Task LoadKernel()
+        private async void LoadKernel()
         {
             Kernel = InstantiateKernel();
 
@@ -40,9 +40,7 @@ namespace MediaBrowser.Common.UI
 
                 await Kernel.Init(progress);
 
-                double seconds = (DateTime.Now - now).TotalSeconds;
-
-                Logger.LogInfo("Kernel.Init completed in {0} seconds.", seconds);
+                Logger.LogInfo("Kernel.Init completed in {0} seconds.", (DateTime.Now - now).TotalSeconds);
                 splash.Close();
 
                 this.ShutdownMode = System.Windows.ShutdownMode.OnLastWindowClose;

+ 9 - 13
MediaBrowser.Controller/FFMpeg/FFProbe.cs

@@ -18,10 +18,7 @@ namespace MediaBrowser.Controller.FFMpeg
             // Use try catch to avoid having to use File.Exists
             try
             {
-                using (FileStream stream = File.OpenRead(outputCachePath))
-                {
-                    return JsonSerializer.DeserializeFromStream<FFProbeResult>(stream);
-                }
+                return GetCachedResult(outputCachePath);
             }
             catch (FileNotFoundException)
             {
@@ -29,7 +26,12 @@ namespace MediaBrowser.Controller.FFMpeg
 
             await Run(item.Path, outputCachePath).ConfigureAwait(false);
 
-            using (FileStream stream = File.OpenRead(outputCachePath))
+            return GetCachedResult(item.Path);
+        }
+
+        public static FFProbeResult GetCachedResult(string path)
+        {
+            using (FileStream stream = File.OpenRead(path))
             {
                 return JsonSerializer.DeserializeFromStream<FFProbeResult>(stream);
             }
@@ -40,10 +42,7 @@ namespace MediaBrowser.Controller.FFMpeg
             // Use try catch to avoid having to use File.Exists
             try
             {
-                using (FileStream stream = File.OpenRead(outputCachePath))
-                {
-                    return JsonSerializer.DeserializeFromStream<FFProbeResult>(stream);
-                }
+                return GetCachedResult(outputCachePath);
             }
             catch (FileNotFoundException)
             {
@@ -51,10 +50,7 @@ namespace MediaBrowser.Controller.FFMpeg
 
             await Run(item.Path, outputCachePath).ConfigureAwait(false);
 
-            using (FileStream stream = File.OpenRead(outputCachePath))
-            {
-                return JsonSerializer.DeserializeFromStream<FFProbeResult>(stream);
-            }
+            return GetCachedResult(item.Path);
         }
 
         private async static Task Run(string input, string output)

+ 3 - 3
MediaBrowser.Controller/IO/DirectoryWatchers.cs

@@ -86,7 +86,7 @@ namespace MediaBrowser.Controller.IO
             await ProcessPathChanges(paths).ConfigureAwait(false);
         }
 
-        private async Task ProcessPathChanges(IEnumerable<string> paths)
+        private Task ProcessPathChanges(IEnumerable<string> paths)
         {
             List<BaseItem> itemsToRefresh = new List<BaseItem>();
 
@@ -105,11 +105,11 @@ namespace MediaBrowser.Controller.IO
                     return folder != null && folder.IsRoot;
                 }))
             {
-                await Kernel.Instance.ReloadRoot().ConfigureAwait(false);
+                return Kernel.Instance.ReloadRoot();
             }
             else
             {
-                await Task.WhenAll(itemsToRefresh.Select(i => Kernel.Instance.ReloadItem(i))).ConfigureAwait(false);
+                return Task.WhenAll(itemsToRefresh.Select(i => Kernel.Instance.ReloadItem(i)));
             }
         }
 

+ 16 - 21
MediaBrowser.Controller/Kernel.cs

@@ -68,21 +68,17 @@ namespace MediaBrowser.Controller
 
         public async override Task Init(IProgress<TaskProgress> progress)
         {
-            await Task.Run(async () =>
-            {
-                await base.Init(progress).ConfigureAwait(false);
+            ExtractFFMpeg();
+            
+            await base.Init(progress).ConfigureAwait(false);
 
-                progress.Report(new TaskProgress() { Description = "Loading Users", PercentComplete = 15 });
-                ReloadUsers();
+            progress.Report(new TaskProgress() { Description = "Loading Users", PercentComplete = 15 });
+            ReloadUsers();
 
-                progress.Report(new TaskProgress() { Description = "Extracting FFMpeg", PercentComplete = 20 });
-                await ExtractFFMpeg().ConfigureAwait(false);
+            progress.Report(new TaskProgress() { Description = "Loading Media Library", PercentComplete = 25 });
+            await ReloadRoot().ConfigureAwait(false);
 
-                progress.Report(new TaskProgress() { Description = "Loading Media Library", PercentComplete = 25 });
-                await ReloadRoot().ConfigureAwait(false);
-
-                progress.Report(new TaskProgress() { Description = "Loading Complete", PercentComplete = 100 });
-            }).ConfigureAwait(false);
+            progress.Report(new TaskProgress() { Description = "Loading Complete", PercentComplete = 100 });
         }
 
         protected override void OnComposablePartsLoaded()
@@ -245,22 +241,21 @@ namespace MediaBrowser.Controller
                     continue;
                 }
 
-                await provider.Fetch(item, args).ConfigureAwait(false);
+                await provider.FetchAsync(item, args).ConfigureAwait(false);
             }
         }
 
+        private void ExtractFFMpeg()
+        {
+            ExtractFFMpeg(ApplicationPaths.FFMpegPath);
+            ExtractFFMpeg(ApplicationPaths.FFProbePath);
+        }
+
         /// <summary>
         /// Run these during Init.
         /// Can't run do this on-demand because there will be multiple workers accessing them at once and we'd have to lock them
         /// </summary>
-        private async Task ExtractFFMpeg()
-        {
-            // FFMpeg.exe
-            await ExtractFFMpeg(ApplicationPaths.FFMpegPath).ConfigureAwait(false);
-            await ExtractFFMpeg(ApplicationPaths.FFProbePath).ConfigureAwait(false);
-        }
-
-        private async Task ExtractFFMpeg(string exe)
+        private async void ExtractFFMpeg(string exe)
         {
             if (File.Exists(exe))
             {

+ 23 - 31
MediaBrowser.Controller/Library/ItemController.cs

@@ -116,14 +116,17 @@ namespace MediaBrowser.Controller.Library
 
             if (item != null)
             {
-                await Kernel.Instance.ExecuteMetadataProviders(item, args);
+                await Kernel.Instance.ExecuteMetadataProviders(item, args).ConfigureAwait(false);
 
-                var folder = item as Folder;
-
-                if (folder != null)
+                if (item.IsFolder)
                 {
                     // If it's a folder look for child entities
-                    await AttachChildren(folder, fileSystemChildren).ConfigureAwait(false);
+                    (item as Folder).Children = (await Task.WhenAll<BaseItem>(GetChildren(item as Folder, fileSystemChildren)).ConfigureAwait(false))
+                        .Where(i => i != null).OrderBy(f =>
+                        {
+                            return string.IsNullOrEmpty(f.SortName) ? f.Name : f.SortName;
+
+                        });
                 }
             }
 
@@ -133,27 +136,18 @@ namespace MediaBrowser.Controller.Library
         /// <summary>
         /// Finds child BaseItems for a given Folder
         /// </summary>
-        private async Task AttachChildren(Folder folder, LazyFileInfo[] fileSystemChildren)
+        private Task<BaseItem>[] GetChildren(Folder folder, LazyFileInfo[] fileSystemChildren)
         {
-            int count = fileSystemChildren.Length;
-
-            Task<BaseItem>[] tasks = new Task<BaseItem>[count];
+            Task<BaseItem>[] tasks = new Task<BaseItem>[fileSystemChildren.Length];
 
-            for (int i = 0; i < count; i++)
+            for (int i = 0; i < fileSystemChildren.Length; i++)
             {
                 var child = fileSystemChildren[i];
 
                 tasks[i] = GetItem(child.Path, folder, child.FileInfo);
             }
 
-            BaseItem[] baseItemChildren = await Task<BaseItem>.WhenAll(tasks).ConfigureAwait(false);
-
-            // Sort them
-            folder.Children = baseItemChildren.Where(i => i != null).OrderBy(f =>
-            {
-                return string.IsNullOrEmpty(f.SortName) ? f.Name : f.SortName;
-
-            });
+            return tasks;
         }
 
         /// <summary>
@@ -216,41 +210,41 @@ namespace MediaBrowser.Controller.Library
         /// <summary>
         /// Gets a Person
         /// </summary>
-        public async Task<Person> GetPerson(string name)
+        public Task<Person> GetPerson(string name)
         {
             string path = Path.Combine(Kernel.Instance.ApplicationPaths.PeoplePath, name);
 
-            return await GetImagesByNameItem<Person>(path, name).ConfigureAwait(false);
+            return GetImagesByNameItem<Person>(path, name);
         }
 
         /// <summary>
         /// Gets a Studio
         /// </summary>
-        public async Task<Studio> GetStudio(string name)
+        public Task<Studio> GetStudio(string name)
         {
             string path = Path.Combine(Kernel.Instance.ApplicationPaths.StudioPath, name);
 
-            return await GetImagesByNameItem<Studio>(path, name).ConfigureAwait(false);
+            return GetImagesByNameItem<Studio>(path, name);
         }
 
         /// <summary>
         /// Gets a Genre
         /// </summary>
-        public async Task<Genre> GetGenre(string name)
+        public Task<Genre> GetGenre(string name)
         {
             string path = Path.Combine(Kernel.Instance.ApplicationPaths.GenrePath, name);
 
-            return await GetImagesByNameItem<Genre>(path, name).ConfigureAwait(false);
+            return GetImagesByNameItem<Genre>(path, name);
         }
 
         /// <summary>
         /// Gets a Year
         /// </summary>
-        public async Task<Year> GetYear(int value)
+        public Task<Year> GetYear(int value)
         {
             string path = Path.Combine(Kernel.Instance.ApplicationPaths.YearPath, value.ToString());
 
-            return await GetImagesByNameItem<Year>(path, value.ToString()).ConfigureAwait(false);
+            return GetImagesByNameItem<Year>(path, value.ToString());
         }
 
         private ConcurrentDictionary<string, object> ImagesByNameItemCache = new ConcurrentDictionary<string, object>();
@@ -258,7 +252,7 @@ namespace MediaBrowser.Controller.Library
         /// <summary>
         /// Generically retrieves an IBN item
         /// </summary>
-        private async Task<T> GetImagesByNameItem<T>(string path, string name)
+        private Task<T> GetImagesByNameItem<T>(string path, string name)
             where T : BaseEntity, new()
         {
             string key = path.ToLower();
@@ -266,12 +260,10 @@ namespace MediaBrowser.Controller.Library
             // Look for it in the cache, if it's not there, create it
             if (!ImagesByNameItemCache.ContainsKey(key))
             {
-                T obj = await CreateImagesByNameItem<T>(path, name).ConfigureAwait(false);
-                ImagesByNameItemCache[key] = obj;
-                return obj;
+                ImagesByNameItemCache[key] = CreateImagesByNameItem<T>(path, name);
             }
 
-            return ImagesByNameItemCache[key] as T;
+            return ImagesByNameItemCache[key] as Task<T>;
         }
 
         /// <summary>

+ 10 - 4
MediaBrowser.Controller/Providers/AudioInfoProvider.cs

@@ -23,16 +23,22 @@ namespace MediaBrowser.Controller.Providers
             get { return MetadataProviderPriority.First; }
         }
 
-        public async override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
+        public async override Task FetchAsync(BaseEntity item, ItemResolveEventArgs args)
         {
             Audio audio = item as Audio;
 
-            string outputDirectory = Path.Combine(Kernel.Instance.ApplicationPaths.FFProbeAudioCacheDirectory, item.Id.ToString().Substring(0, 1));
+            Fetch(audio, await FFProbe.Run(audio, GetFFProbeOutputPath(item)).ConfigureAwait(false));
+        }
 
-            string outputPath = Path.Combine(outputDirectory, item.Id + "-" + item.DateModified.Ticks + ".js");
+        private string GetFFProbeOutputPath(BaseEntity item)
+        {
+            string outputDirectory = Path.Combine(Kernel.Instance.ApplicationPaths.FFProbeAudioCacheDirectory, item.Id.ToString().Substring(0, 1));
 
-            FFProbeResult data = await FFProbe.Run(audio, outputPath).ConfigureAwait(false);
+            return Path.Combine(outputDirectory, item.Id + "-" + item.DateModified.Ticks + ".js");
+        }
 
+        private void Fetch(Audio audio, FFProbeResult data)
+        {
             MediaStream stream = data.streams.First(s => s.codec_type.Equals("audio", StringComparison.OrdinalIgnoreCase));
 
             string bitrate = null;

+ 1 - 1
MediaBrowser.Controller/Providers/BaseMetadataProvider.cs

@@ -31,7 +31,7 @@ namespace MediaBrowser.Controller.Providers
             }
         }
 
-        public abstract Task Fetch(BaseEntity item, ItemResolveEventArgs args);
+        public abstract Task FetchAsync(BaseEntity item, ItemResolveEventArgs args);
 
         public abstract MetadataProviderPriority Priority { get; }
     }

+ 4 - 2
MediaBrowser.Controller/Providers/FolderProviderFromXml.cs

@@ -19,14 +19,16 @@ namespace MediaBrowser.Controller.Providers
             get { return MetadataProviderPriority.First; }
         }
 
-        public async override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
+        public override Task FetchAsync(BaseEntity item, ItemResolveEventArgs args)
         {
             var metadataFile = args.GetFileSystemEntryByName("folder.xml");
 
             if (metadataFile.HasValue)
             {
-                await Task.Run(() => { new FolderXmlParser().Fetch(item as Folder, metadataFile.Value.Path); }).ConfigureAwait(false);
+                return Task.Run(() => { new FolderXmlParser().Fetch(item as Folder, metadataFile.Value.Path); });
             }
+
+            return Task.FromResult<object>(null);
         }
     }
 }

+ 14 - 15
MediaBrowser.Controller/Providers/ImageFromMediaLocationProvider.cs

@@ -21,24 +21,23 @@ namespace MediaBrowser.Controller.Providers
             get { return MetadataProviderPriority.First; }
         }
 
-        public override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
+        public override Task FetchAsync(BaseEntity item, ItemResolveEventArgs args)
         {
-            return Task.Run(() =>
+            if (args.IsDirectory)
             {
-                if (args.IsDirectory)
+                var baseItem = item as BaseItem;
+
+                if (baseItem != null)
+                {
+                    return Task.Run(() => { PopulateImages(baseItem, args); });
+                }
+                else
                 {
-                    var baseItem = item as BaseItem;
-
-                    if (baseItem != null)
-                    {
-                        PopulateImages(baseItem, args);
-                    }
-                    else
-                    {
-                        PopulateImages(item, args);
-                    }
+                    return Task.Run(() => { PopulateImages(item, args); });
                 }
-            });
+            }
+
+            return Task.FromResult<object>(null);
         }
 
         /// <summary>
@@ -49,7 +48,7 @@ namespace MediaBrowser.Controller.Providers
             for (int i = 0; i < args.FileSystemChildren.Length; i++)
             {
                 var file = args.FileSystemChildren[i];
-                
+
                 string filePath = file.Path;
 
                 string ext = Path.GetExtension(filePath);

+ 3 - 7
MediaBrowser.Controller/Providers/LocalTrailerProvider.cs

@@ -20,10 +20,8 @@ namespace MediaBrowser.Controller.Providers
             get { return MetadataProviderPriority.First; }
         }
 
-        public async override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
+        public async override Task FetchAsync(BaseEntity item, ItemResolveEventArgs args)
         {
-            BaseItem baseItem = item as BaseItem;
-
             var trailerPath = args.GetFileSystemEntryByName("trailers", true);
 
             if (trailerPath.HasValue)
@@ -36,9 +34,7 @@ namespace MediaBrowser.Controller.Providers
                 {
                     string file = allFiles[i];
 
-                    BaseItem child = await Kernel.Instance.ItemController.GetItem(file).ConfigureAwait(false);
-
-                    Video video = child as Video;
+                    Video video = await Kernel.Instance.ItemController.GetItem(file).ConfigureAwait(false) as Video;
 
                     if (video != null)
                     {
@@ -46,7 +42,7 @@ namespace MediaBrowser.Controller.Providers
                     }
                 }
 
-                baseItem.LocalTrailers = localTrailers;
+                (item as BaseItem).LocalTrailers = localTrailers;
             }
         }
     }

+ 7 - 4
MediaBrowser.Controller/Providers/VideoInfoProvider.cs

@@ -24,7 +24,7 @@ namespace MediaBrowser.Controller.Providers
             get { return MetadataProviderPriority.Second; }
         }
 
-        public override async Task Fetch(BaseEntity item, ItemResolveEventArgs args)
+        public override async Task FetchAsync(BaseEntity item, ItemResolveEventArgs args)
         {
             Video video = item as Video;
 
@@ -39,11 +39,14 @@ namespace MediaBrowser.Controller.Providers
                 return;
             }
 
-            string outputDirectory = Path.Combine(Kernel.Instance.ApplicationPaths.FFProbeVideoCacheDirectory, item.Id.ToString().Substring(0, 1));
+            Fetch(video, await FFProbe.Run(video, GetFFProbeOutputPath(video)).ConfigureAwait(false));
+        }
 
-            string outputPath = Path.Combine(outputDirectory, item.Id + "-" + item.DateModified.Ticks + ".js");
+        private string GetFFProbeOutputPath(Video item)
+        {
+            string outputDirectory = Path.Combine(Kernel.Instance.ApplicationPaths.FFProbeVideoCacheDirectory, item.Id.ToString().Substring(0, 1));
 
-            FFProbeResult data = await FFProbe.Run(video, outputPath).ConfigureAwait(false);
+            return Path.Combine(outputDirectory, item.Id + "-" + item.DateModified.Ticks + ".js");
         }
 
         private void Fetch(Video video, FFProbeResult data)

+ 0 - 2
MediaBrowser.Controller/Xml/BaseItemXmlParser.cs

@@ -1,8 +1,6 @@
 using System;
 using System.Collections.Generic;
-using System.IO;
 using System.Linq;
-using System.Threading.Tasks;
 using System.Xml;
 using MediaBrowser.Model.Entities;
 

+ 4 - 2
MediaBrowser.Movies/Providers/MovieProviderFromXml.cs

@@ -21,14 +21,16 @@ namespace MediaBrowser.Movies.Providers
             get { return MetadataProviderPriority.First; }
         }
 
-        public async override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
+        public override Task FetchAsync(BaseEntity item, ItemResolveEventArgs args)
         {
             var metadataFile = args.GetFileSystemEntryByName("movie.xml");
 
             if (metadataFile.HasValue)
             {
-                await Task.Run(() => { new BaseItemXmlParser<Movie>().Fetch(item as Movie, metadataFile.Value.Path); }).ConfigureAwait(false);
+                return Task.Run(() => { new BaseItemXmlParser<Movie>().Fetch(item as Movie, metadataFile.Value.Path); });
             }
+
+            return Task.FromResult<object>(null);
         }
     }
 }

+ 2 - 3
MediaBrowser.TV/Providers/EpisodeImageFromMediaLocationProvider.cs

@@ -1,5 +1,4 @@
-using System;
-using System.ComponentModel.Composition;
+using System.ComponentModel.Composition;
 using System.IO;
 using System.Linq;
 using System.Threading.Tasks;
@@ -23,7 +22,7 @@ namespace MediaBrowser.TV.Providers
             get { return MetadataProviderPriority.First; }
         }
 
-        public override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
+        public override Task FetchAsync(BaseEntity item, ItemResolveEventArgs args)
         {
             return Task.Run(() =>
             {

+ 12 - 15
MediaBrowser.TV/Providers/EpisodeProviderFromXml.cs

@@ -22,24 +22,21 @@ namespace MediaBrowser.TV.Providers
             get { return MetadataProviderPriority.First; }
         }
 
-        public async override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
+        public override Task FetchAsync(BaseEntity item, ItemResolveEventArgs args)
         {
-            await Task.Run(() =>
-            {
-                string metadataFolder = Path.Combine(args.Parent.Path, "metadata");
-
-                Episode episode = item as Episode;
-
-                string episodeFileName = Path.GetFileName(episode.Path);
+            return Fetch(item, args);
+        }
 
-                string metadataFile = Path.Combine(metadataFolder, Path.ChangeExtension(episodeFileName, ".xml"));
+        private Task Fetch(BaseEntity item, ItemResolveEventArgs args)
+        {
+            string metadataFolder = Path.Combine(args.Parent.Path, "metadata");
 
-                FetchMetadata(episode, args.Parent as Season, metadataFile);
+            string metadataFile = Path.Combine(metadataFolder, Path.ChangeExtension(Path.GetFileName(args.Path), ".xml"));
 
-            }).ConfigureAwait(false);
+            return FetchMetadata(item as Episode, args.Parent as Season, metadataFile);
         }
 
-        private void FetchMetadata(Episode item, Season season, string metadataFile)
+        private Task FetchMetadata(Episode item, Season season, string metadataFile)
         {
             if (season == null)
             {
@@ -47,18 +44,18 @@ namespace MediaBrowser.TV.Providers
                 // Need to validate it the slow way
                 if (!File.Exists(metadataFile))
                 {
-                    return;
+                    return Task.FromResult<object>(null);
                 }
             }
             else
             {
                 if (!season.ContainsMetadataFile(metadataFile))
                 {
-                    return;
+                    return Task.FromResult<object>(null);
                 }
             }
 
-            new EpisodeXmlParser().Fetch(item, metadataFile);
+            return Task.Run(() => { new EpisodeXmlParser().Fetch(item, metadataFile); });
         }
     }
 }

+ 4 - 2
MediaBrowser.TV/Providers/SeriesProviderFromXml.cs

@@ -21,14 +21,16 @@ namespace MediaBrowser.TV.Providers
             get { return MetadataProviderPriority.First; }
         }
 
-        public async override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
+        public override Task FetchAsync(BaseEntity item, ItemResolveEventArgs args)
         {
             var metadataFile = args.GetFileSystemEntryByName("series.xml");
 
             if (metadataFile.HasValue)
             {
-                await Task.Run(() => { new SeriesXmlParser().Fetch(item as Series, metadataFile.Value.Path); }).ConfigureAwait(false);
+                return Task.Run(() => { new SeriesXmlParser().Fetch(item as Series, metadataFile.Value.Path); });
             }
+
+            return Task.FromResult<object>(null);
         }
     }
 }