我一直在使用Youtube V3 API,但我似乎无法在Windows窗体中使用它。我得到了示例代码,所以我知道我的API密钥正常工作,但是当我尝试从控制台应用程序转换它时,代码挂起就行了,
var searchListResponse = await searchListRequest.ExecuteAsync();
我还没有找到与此问题相关的任何内容,没有编译错误或抛出运行时错误。任何帮助将不胜感激!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Upload;
using Google.Apis.Util.Store;
using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data;
namespace MiddleManYTDL
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
MessageBox.Show("YouTube Data API: Search");
try
{
new Form1().Run().Wait();
}
catch (AggregateException exs)
{
foreach (var ex in exs.InnerExceptions)
{
MessageBox.Show("Error: " + ex.Message);
}
}
}
private async Task Run()
{
var youtubeService = new YouTubeService(new BaseClientService.Initializer()
{
ApiKey = "My API Key",
ApplicationName = this.GetType().ToString()
});
var searchListRequest = youtubeService.Search.List("snippet");
searchListRequest.Q = "Google"; // Replace with your search term.
searchListRequest.MaxResults = 10;
MessageBox.Show("This will Display");
// Call the search.list method to retrieve results matching the specified query term.
var searchListResponse = await searchListRequest.ExecuteAsync();
MessageBox.Show("This never gets executed");
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;
}
}
MessageBox.Show(String.Format("Videos:\n{0}\n", string.Join("\n", videos)));
MessageBox.Show(String.Format("Channels:\n{0}\n", string.Join("\n", channels)));
MessageBox.Show(String.Format("Playlists:\n{0}\n", string.Join("\n", playlists)));
}
}
}
答案 0 :(得分:3)
这与YouTube API无关。您的问题出现在以下行的阻止Wait()
调用中:
new Form1().Run().Wait();
正在发生的事情是您的代码到达Run()
并同步执行方法的一部分,直到await
关键字(在您的情况下 - 在UI线程上)。然后,当await
正在进行时,执行将返回到Form.Load
处理程序,该处理程序立即命中Wait()
调用并阻止UI线程,直到Run()
返回任务为止已经完成了。在此之后的某个时刻await
内的Run()
任务完成,异步状态机尝试在UI线程上执行Run()
方法的其余部分。现在你有Wait()
阻止UI线程,等待Run()
完成,Run()
等待UI线程可用,以便{{1}的其余部分方法可以执行。两者都无法取得任何进展。每当async
方法与阻止async/await
或Wait()
调用混合时,此死锁情况就非常常见。
有两种可能的解决方法:
Result
(即在呼叫层次结构中没有阻止async/await
和Wait()
调用)Result
方法,以便在Run()
之后不会访问任何UI元素,并使用await
阻止ConfigureAwait(false)
捕获,然后回发到同步安装在UI线程上的上下文(意味着await
之后的方法部分将在线程池线程上执行。)我个人选择#1选项:
await
以下是一些优秀的博客文章,详细讨论了您正在观察的问题:
http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html http://blogs.msdn.com/b/pfxteam/archive/2011/01/13/10115163.aspx