Winforms Youtube API v3错误-挂起等待searchListRequest.ExecuteAsync();
我一直在玩Youtube V3 API,但我似乎无法让它在windows窗体中工作。我让示例代码正常工作,所以我知道我的API密钥工作正常,但当我尝试从控制台应用程序转换它时,代码挂起在这一行 var searchListResponse=等待searchListRequest.ExecuteAsync 我还没有找到任何与此问题相关的内容,没有出现编译错误或抛出运行时错误。任何帮助都将不胜感激Winforms Youtube API v3错误-挂起等待searchListRequest.ExecuteAsync();,winforms,Winforms,我一直在玩Youtube V3 API,但我似乎无法让它在windows窗体中工作。我让示例代码正常工作,所以我知道我的API密钥工作正常,但当我尝试从控制台应用程序转换它时,代码挂起在这一行 var searchListResponse=等待searchListRequest.ExecuteAsync 我还没有找到任何与此问题相关的内容,没有出现编译错误或抛出运行时错误。任何帮助都将不胜感激 using System; using System.Collections.Generic; usi
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)));
}
}
}
这与YouTube API本身无关。您的问题在于以下线路上的阻塞等待呼叫:
new Form1().Run().Wait();
发生的事情是,您的代码开始运行,并在UI线程上同步执行方法的一部分,直到wait关键字。然后,在等待过程中,执行返回到Form.Load处理程序,该处理程序立即点击等待调用并阻塞UI线程,直到Run返回的任务完成。在运行中等待的任务完成之后的某个时刻,异步状态机尝试在UI线程上执行剩余的Run方法。现在,您已经在等待运行完成时阻塞了UI线程,并在等待UI线程可用时运行,以便可以执行异步方法的其余部分。两者都不能取得任何进展。当异步/等待方法和阻塞等待或结果调用混合时,这种死锁场景非常常见
有两种可能的修复方法:
始终使用异步/等待,即在调用层次结构中不阻塞等待和结果调用
重写您的Run方法,以便在等待之后不会访问任何UI元素,并使用ConfigureWaitFalse防止等待捕获并随后发回安装在UI线程上的同步上下文,这意味着等待之后的方法部分将在线程池线程上执行。
就个人而言,我会选择选项1:
private async void Form1_Load(object sender, EventArgs e)
{
MessageBox.Show("YouTube Data API: Search");
try
{
await new Form1().Run();
}
catch (Exception ex)
{
// Exception dispatch is different with async/await,
// so you don't get the AggregateException - rather
// just the first exception which caused the task
// to fault.
MessageBox.Show("Error: " + ex.Message);
}
}
以下是一些优秀的博客文章,详细讨论了您正在观察的问题: