坚持使用 ASP.NET MVC4 中的 Google API YouTube 搜索示例?
Stuck with the Google API YouTube Search example in ASP.NET MVC4?
卡了好几天了,希望有人能帮帮我。
我一直在尝试在 VS 2013 Express for Web MVC4 项目中 运行 来自 Google's API examples for .net 的 YouTube 'Search by keyword' 示例,并且 ExecuteAsync()
调用 Google API 再也回不来了。
我相信示例代码可以正常工作,因为我在 VS 2013 Express 中针对 Windows Desktop 作为控制台应用程序对其进行了测试,并且返回正常。 google 的开发者控制台中的统计数据也告诉我正在接收 API 请求。
这是我所做的:
我创建了一个名为 GoogleTest 的新 VS 2013 Express for Web MVC4 项目并安装了 'Install-Package Google.Apis.YouTube.v3' 包。
然后我添加了以下模型。
public class SearchYouTube
{
public int ID { get; set; }
public async Task RunYouTube()
{
var youtubeService = new YouTubeService(new BaseClientService.Initializer()
{
ApiKey = " <MY DEVELOPER KEY HERE> ",
ApplicationName = this.GetType().ToString()
});
var searchListRequest = youtubeService.Search.List("snippet");
searchListRequest.Q = "googleapi examples"; // Replace with your search term.
searchListRequest.MaxResults = 50;
// Call the search.list method to retrieve results matching the specified query term.
var searchListResponse = await searchListRequest.ExecuteAsync();
List<string> videos = new List<string>();
List<string> channels = new List<string>();
List<string> playlists = new List<string>();
// Add each result to the appropriate list, and then display the lists of
// matching videos, channels, and playlists.
foreach (var searchResult in searchListResponse.Items)
{
switch (searchResult.Id.Kind)
{
case "youtube#video":
videos.Add(String.Format("{0} ({1})", searchResult.Snippet.Title, searchResult.Id.VideoId));
break;
case "youtube#channel":
channels.Add(String.Format("{0} ({1})", searchResult.Snippet.Title, searchResult.Id.ChannelId));
break;
case "youtube#playlist":
playlists.Add(String.Format("{0} ({1})", searchResult.Snippet.Title, searchResult.Id.PlaylistId));
break;
}
}
Console.WriteLine(String.Format("Videos:\n{0}\n", string.Join("\n", videos)));
Console.WriteLine(String.Format("Channels:\n{0}\n", string.Join("\n", channels)));
Console.WriteLine(String.Format("Playlists:\n{0}\n", string.Join("\n", playlists)));
}
}
然后我在 Home 控制器中调用上面的 class 像这样:
public ActionResult Index()
{
ViewBag.Message = "MVC example";
SearchYouTube searchObject = new SearchYouTube();
searchObject.RunYouTube().Wait();
return View();
}
运行 这在调试器中,程序进入但从未从 returns 上面 SearchYouTube
class 中的这一行开始:
var searchListResponse = await searchListRequest.ExecuteAsync();
任何人都可以帮助解释我做错了什么或我错过了什么吗??
你手上好像出现了死锁,因为你在做"sync over async"。当您使用 Task.Wait
时,您正在阻塞并浪费一个线程。内部 async
操作(即 await searchListRequest.ExecuteAsync();
)完成后,显然需要同一个线程继续处理该方法的其余部分。
所有这些都是由于 ASP.Net 中存在的 SynchronizationContext
而发生的,它在使用 await
时被捕获,以便将继续发布到它。当您使用 ConfigureAwait(false)
时,您正在将延续配置为在捕获的上下文中不 运行 并使用 ThreadPool
代替。
在控制台应用程序中没有 SC,因此 ThreadPool
上的每个延续 运行s。就好像每个 await
都有 ConfigureAwait(false)
.
要解决此死锁,您可以使用 ConfigureAwait(false)
或什至更好,使 MVC 方法 async
这样您就不需要同步阻塞 (more on async
in MVC):
public async Task<ActionResult> Index()
{
ViewBag.Message = "MVC example";
SearchYouTube searchObject = new SearchYouTube();
await searchObject.RunYouTube();
return View();
}
卡了好几天了,希望有人能帮帮我。
我一直在尝试在 VS 2013 Express for Web MVC4 项目中 运行 来自 Google's API examples for .net 的 YouTube 'Search by keyword' 示例,并且 ExecuteAsync()
调用 Google API 再也回不来了。
我相信示例代码可以正常工作,因为我在 VS 2013 Express 中针对 Windows Desktop 作为控制台应用程序对其进行了测试,并且返回正常。 google 的开发者控制台中的统计数据也告诉我正在接收 API 请求。
这是我所做的:
我创建了一个名为 GoogleTest 的新 VS 2013 Express for Web MVC4 项目并安装了 'Install-Package Google.Apis.YouTube.v3' 包。
然后我添加了以下模型。
public class SearchYouTube
{
public int ID { get; set; }
public async Task RunYouTube()
{
var youtubeService = new YouTubeService(new BaseClientService.Initializer()
{
ApiKey = " <MY DEVELOPER KEY HERE> ",
ApplicationName = this.GetType().ToString()
});
var searchListRequest = youtubeService.Search.List("snippet");
searchListRequest.Q = "googleapi examples"; // Replace with your search term.
searchListRequest.MaxResults = 50;
// Call the search.list method to retrieve results matching the specified query term.
var searchListResponse = await searchListRequest.ExecuteAsync();
List<string> videos = new List<string>();
List<string> channels = new List<string>();
List<string> playlists = new List<string>();
// Add each result to the appropriate list, and then display the lists of
// matching videos, channels, and playlists.
foreach (var searchResult in searchListResponse.Items)
{
switch (searchResult.Id.Kind)
{
case "youtube#video":
videos.Add(String.Format("{0} ({1})", searchResult.Snippet.Title, searchResult.Id.VideoId));
break;
case "youtube#channel":
channels.Add(String.Format("{0} ({1})", searchResult.Snippet.Title, searchResult.Id.ChannelId));
break;
case "youtube#playlist":
playlists.Add(String.Format("{0} ({1})", searchResult.Snippet.Title, searchResult.Id.PlaylistId));
break;
}
}
Console.WriteLine(String.Format("Videos:\n{0}\n", string.Join("\n", videos)));
Console.WriteLine(String.Format("Channels:\n{0}\n", string.Join("\n", channels)));
Console.WriteLine(String.Format("Playlists:\n{0}\n", string.Join("\n", playlists)));
}
}
然后我在 Home 控制器中调用上面的 class 像这样:
public ActionResult Index()
{
ViewBag.Message = "MVC example";
SearchYouTube searchObject = new SearchYouTube();
searchObject.RunYouTube().Wait();
return View();
}
运行 这在调试器中,程序进入但从未从 returns 上面 SearchYouTube
class 中的这一行开始:
var searchListResponse = await searchListRequest.ExecuteAsync();
任何人都可以帮助解释我做错了什么或我错过了什么吗??
你手上好像出现了死锁,因为你在做"sync over async"。当您使用 Task.Wait
时,您正在阻塞并浪费一个线程。内部 async
操作(即 await searchListRequest.ExecuteAsync();
)完成后,显然需要同一个线程继续处理该方法的其余部分。
所有这些都是由于 ASP.Net 中存在的 SynchronizationContext
而发生的,它在使用 await
时被捕获,以便将继续发布到它。当您使用 ConfigureAwait(false)
时,您正在将延续配置为在捕获的上下文中不 运行 并使用 ThreadPool
代替。
在控制台应用程序中没有 SC,因此 ThreadPool
上的每个延续 运行s。就好像每个 await
都有 ConfigureAwait(false)
.
要解决此死锁,您可以使用 ConfigureAwait(false)
或什至更好,使 MVC 方法 async
这样您就不需要同步阻塞 (more on async
in MVC):
public async Task<ActionResult> Index()
{
ViewBag.Message = "MVC example";
SearchYouTube searchObject = new SearchYouTube();
await searchObject.RunYouTube();
return View();
}