首页 > 解决方案 > 如何将代码 YouTube API 从控制台转换为 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();

我不明白为什么它会停止?请帮我解决

标签: c#wpfyoutube-api

解决方案


您必须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对于允许正确的异​​常处理/行为很重要。如果你不这样做awaitTask那么异常将不会正确传播——异常将被吞没。这是因为在async方法中异常被捕获并放置在Task对象上。当您await使用时Task,您允许执行传播到调用者的上下文以最终保存您的应用程序或在一个catch块中处理。

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

首先确保您的调试器将通过至少启用所有 CLR 异常来中断所有异常:在主菜单中选择Debug/Windows/Exception Setting并选中“Common Language Runtime Exceptions”复选框。

如果在调试器中仍然没有抛出异常,则删除ExecuteAsync()以同步执行操作。这样您就可以测试是否遇到死锁。当谈到 async/await 时,您必须知道控制台应用程序、Asp.Net 和 Winforms/Wpf/UWP 在某些方面具有不同的行为。


推荐阅读