如何将代码 YouTube API 从控制台转换为 WPF

How to convert code YouTube API from Console to WPF

我的代码在控制台中运行良好,但我尝试将其转换为 WPF c#,但没有成功。 我尝试将每个部分移植到 WPF,当我将它转换为 WPF 时,我发现了下面的代码(我在下面引用的第二个代码)它不起作用 请帮我。如何在 WPF C# 中正常工作 这是我的代码:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Threading;
    using System.Threading.Tasks;
    
    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 ConsoleApp2
    {
        
        internal class PlaylistUpdates
        {
            public string PrivacyStatus { get; private set; }
    
            [STAThread]
            static void Main(string[] args)
            {
                Console.WriteLine("YouTube Data API: Playlist Updates");
                Console.WriteLine("==================================");
    
                try
                {
                     //new PlaylistUpdates().Run().Wait();
                    //new PlaylistUpdates().RunUpload().Wait();
                    new PlaylistUpdates().Editvideo().Wait();
                    
                }
                catch (AggregateException ex)
                {
                    foreach (var e in ex.InnerExceptions)
                    {
                        Console.WriteLine("Error: " + e.Message);
                    }
                }
    
                Console.WriteLine("Press any key to continue...");
                Console.ReadKey();
            }

            private async Task Editvideo()
            {
                UserCredential credential;
                using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
                {
                    credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                        GoogleClientSecrets.Load(stream).Secrets,
                        // This OAuth 2.0 access scope allows for read-only access to the authenticated 
                        // user's account, but not other types of account access.
                        new[] { YouTubeService.Scope.YoutubeReadonly },
                        "user",
                        CancellationToken.None,
                        new FileDataStore(this.GetType().ToString())
                    );
                }
    
                var youtubeService = new YouTubeService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = this.GetType().ToString()
                });
    
                var channelsListRequest = youtubeService.Channels.List("contentDetails");
                channelsListRequest.Mine = true;
    
                // Retrieve the contentDetails part of the channel resource for the authenticated user's channel.
                var channelsListResponse = await channelsListRequest.ExecuteAsync();
    
                foreach (var channel in channelsListResponse.Items)
                {
                    // From the API response, extract the playlist ID that identifies the list
                    // of videos uploaded to the authenticated user's channel.
                    var uploadsListId = channel.ContentDetails.RelatedPlaylists.Uploads;
    
                    Console.WriteLine("Videos in list {0}", uploadsListId);
    
                    var nextPageToken = "";
                    while (nextPageToken != null)
                    {
                        var playlistItemsListRequest = youtubeService.PlaylistItems.List("snippet,status");
                        playlistItemsListRequest.PlaylistId = uploadsListId;
                        playlistItemsListRequest.MaxResults = 50;
                        playlistItemsListRequest.PageToken = nextPageToken;
    
                        // Create a new, private playlist in the authorized user's channel.
                        var newVideo = new Video();
                        newVideo.Snippet = new VideoSnippet();
                        newVideo.Id = "6obQQde1X3A";
                        newVideo.Snippet.Title = "My Title";
                        newVideo.Snippet.Description = "My Description";
                        newVideo.Snippet.Tags = new string[] { "tag 1", "tag 2", "tag 3" };
                        newVideo.Snippet.CategoryId = "22";
                        newVideo.Status = new VideoStatus();
                        newVideo.Status.PrivacyStatus = "public";
                        newVideo = await youtubeService.Videos.Update(newVideo,"Id,snippet,status").ExecuteAsync();
    
                        Console.WriteLine("Change video details OK ....");
     
                        // Retrieve the list of videos uploaded to the authenticated user's channel.
                        var playlistItemsListResponse = await playlistItemsListRequest.ExecuteAsync();
    
                        foreach (var playlistItem in playlistItemsListResponse.Items)
                        {
                        Console.WriteLine("{0} ({1})", playlistItem.Snippet.Title, playlistItem.Snippet.ResourceId.VideoId);
                        }
    
                        nextPageToken = playlistItemsListResponse.NextPageToken;
                    }
                }
            }
    }
    
    }

如果我删除下面的这段代码。效果很好!

// Create a new, private playlist in the authorized user's channel.
                        var newVideo = new Video();
                        newVideo.Snippet = new VideoSnippet();
                        newVideo.Id = "6obQQde1X3A";
                        newVideo.Snippet.Title = "My Title";
                        newVideo.Snippet.Description = "My Description";
                        newVideo.Snippet.Tags = new string[] { "tag 1", "tag 2", "tag 3" };
                        newVideo.Snippet.CategoryId = "22";
                        newVideo.Status = new VideoStatus();
                        newVideo.Status.PrivacyStatus = "public";
                        newVideo = await youtubeService.Videos.Update(newVideo,"Id,snippet,status").ExecuteAsync();
    
                        Console.WriteLine("Change video details OK ....");

这是我在 WPF 中的代码

 private async Task Change_VideoDetails()
    {
        UserCredential credential;
        using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
        {
            credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                GoogleClientSecrets.Load(stream).Secrets,
                new[] { YouTubeService.Scope.YoutubeReadonly },
                "user",
                CancellationToken.None,
                new FileDataStore(this.GetType().ToString())
            );
        }

        var youtubeService = new YouTubeService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = credential,
            ApplicationName = this.GetType().ToString()
        });
        var channelsListRequest = youtubeService.Channels.List("contentDetails");
        channelsListRequest.Mine = true;
        // Retrieve the contentDetails part of the channel resource for the authenticated user's channel.
        var channelsListResponse = await channelsListRequest.ExecuteAsync();

        foreach (var channel in channelsListResponse.Items)
        {
            // From the API response, extract the playlist ID that identifies the list
            // of videos uploaded to the authenticated user's channel.
            var uploadsListId = channel.ContentDetails.RelatedPlaylists.Uploads;

            //Console.WriteLine("Videos in list {0}", uploadsListId);

            var nextPageToken = "";
            while (nextPageToken != null)
            {
                var playlistItemsListRequest = youtubeService.PlaylistItems.List("Id,snippet,status");
                playlistItemsListRequest.PlaylistId = uploadsListId;
                playlistItemsListRequest.MaxResults = 50;
                playlistItemsListRequest.PageToken = nextPageToken;

                 var newVideo = new Video();
                newVideo.Snippet = new VideoSnippet();
                newVideo.Id = "6obQQde1X3A";
                txtLog.AppendText("\nWill change video details....." + newVideo.Id + );
                txtLog.ScrollToEnd();

                newVideo.Snippet = new VideoSnippet();
                newVideo.Id = "6obQQde1X3A";
                newVideo.Snippet.Title = "My Title";
                newVideo.Snippet.Description = "My Description";
                newVideo.Snippet.Tags = new string[] { "tag 1", "tag 2", "tag 3" };
                newVideo.Snippet.CategoryId = "22";
                newVideo.Status = new VideoStatus();
                newVideo.Status.PrivacyStatus = "public";
                newVideo = await youtubeService.Videos.Update(newVideo, "Id,snippet,status").ExecuteAsync();

                txtLog.AppendText("\nChanged video details ....." + newVideo.Id);
                txtLog.ScrollToEnd();

                // Retrieve the list of videos uploaded to the authenticated user's channel.
                var playlistItemsListResponse = await playlistItemsListRequest.ExecuteAsync();
                int line_count=0;
                foreach (var playlistItem in playlistItemsListResponse.Items)
                {
                    
                    line_count += 1;
                    if (line_count == int.Parse(txtVideonumber.Text))
                    {
                        break;
                    }


                    //}   

                }

                nextPageToken = playlistItemsListResponse.NextPageToken;
            }
        }
    }

我在上面的代码 运行 中使用了下面的代码:

private void BtnChange_Click(object sender, RoutedEventArgs e)
    {
        Change_VideoDetails();
    }

我尝试了 运行 调试器,但我的代码在以下代码处停止:

 newVideo = await youtubeService.Videos.Update(newVideo, "Id,snippet,status").ExecuteAsync();

我不明白为什么要停止?请帮我解决一下

您必须 await 异步方法,即 await Task 结果:

// Since this is an event handler 'async void' is allowed. 
// Otherwise you must use 'async Task' or 'async Task<T>'
private async void BtnChange_Click(object sender, RoutedEventArgs e)
{
  await Change_VideoDetails();
}

等待 Task 对允许适当的例外很重要 handling/behavior。如果您不 await a Task 那么异常将不会正确传播 - 异常将被吞噬。这是因为在 async 方法中,异常被捕获并放置在 Task 对象上。当您 await Task 时,您允许执行传播到调用者的上下文以最终保留您的应用程序或在 catch 块中处理。

对于无法访问您的环境(包括 Youtube 帐户和身份验证配置)的人来说,您的问题很难解决。

首先通过至少启用所有 CLR 异常来确保您的调试器将在所有异常上中断:select Debug/ Windows/Exception Setting in the main菜单并选中 “公共语言运行时异常” 复选框。

如果调试器仍然没有异常抛出,去掉ExecuteAsync()同步执行操作。这样就可以测试是否遇到死锁。说到 async/await 你一定知道控制台应用程序,Asp.Net 和 Winforms/Wpf/UWP 在某些方面有不同的行为。