【问题标题】:Functions aren't finishing before starting the next功能在开始下一个之前没有完成
【发布时间】:2017-09-14 19:31:22
【问题描述】:

我有一个 youtube 上传器,我正在从一个音频文件生成一个视频,效果很好,但是当我上传到 Youtube 时,当我试图等待它完成上传后再重复时,程序仍然运行

我在这里生成一个视频:

    private void button2_Click(object sender, EventArgs e)
    {
        if (status.Text == "Stopped")
        {
            if (!generatearticle.IsBusy)
            {
                // started
                status.Text = "Started";
                status.ForeColor = System.Drawing.Color.Green;
                start.Text = "Stop Generating";
                generatearticle.RunWorkerAsync();
            }
        }
        else
        {
            if(generatearticle.IsBusy)
            {
                generatearticle.CancelAsync();
                // started
                status.Text = "Stopped";
                status.ForeColor = System.Drawing.Color.Red;
                start.Text = "Start Generating";
            }
        }
    }

    private void core()
    { 
        // generate audio
        int i = 0;
        for (int n = 1; n < co; n++)
        {
            // generate video and upload to
            // youtube, this generates, but
            // when uploading to youtube this for
            // loop carries on when I want it to
            // upload to youtube first before carrying on
            generatevideo(image, articlename);
        }
    }

    private void generateVideo(string images, String articlename)
    {
       //generate the video here, once done upload
       {code removed, this just generates a video, nothing important}

       // now upload (but I want it to finish before repeating the core() function
       try
            {
                new UploadVideo().Run(articlename, file);

            }
            catch (AggregateException ex)
            {
                foreach (var e in ex.InnerExceptions)
                {
                    ThreadSafe(() =>
                    {
                        this.Invoke((MethodInvoker)delegate
                        {
                            status.Text = e.Message;
                            status.ForeColor = System.Drawing.Color.Red;
                        });
                    });
                }
            }
    }

我如何上传到 Youtube:

using System;
using System.IO;
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 articletoyoutube
{
    /// <summary>
    /// YouTube Data API v3 sample: upload a video.
    /// Relies on the Google APIs Client Library for .NET, v1.7.0 or higher.
    /// See https://code.google.com/p/google-api-dotnet-client/wiki/GettingStarted
    /// </summary>
    class UploadVideo
    {
        // to access form controlls
        Form1 core = new Form1();

        public async Task Run(string articlename, string filelocation)
        {
            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 an application to upload files to the
                    // authenticated user's YouTube channel, but doesn't allow other types of access.
                    new[] {
                        YouTubeService.Scope.YoutubeUpload
                    },
                    "user",
                    CancellationToken.None
                );
            }


            var youtubeService = new YouTubeService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName = Assembly.GetExecutingAssembly().GetName().Name
            });

            var video = new Video();
            video.Snippet = new VideoSnippet();
            video.Snippet.Title = articlename;
            video.Snippet.Description = "News story regarding" + articlename;
            video.Snippet.Tags = new string[] {
                "news",
                "breaking",
                "important"
            };
            video.Snippet.CategoryId = "25"; // See https://developers.google.com/youtube/v3/docs/videoCategories/list
            video.Status = new VideoStatus();
            video.Status.PrivacyStatus = "public"; // or "private" or "public"
            var filePath = filelocation; // Replace with path to actual movie file.

            using (var fileStream = new FileStream(filePath, FileMode.Open))
            {
                var videosInsertRequest = youtubeService.Videos.Insert(video, "snippet,status", fileStream, "video/*");
                videosInsertRequest.ProgressChanged += videosInsertRequest_ProgressChanged;
                videosInsertRequest.ResponseReceived += videosInsertRequest_ResponseReceived;

                await videosInsertRequest.UploadAsync();
            }
        }

        void videosInsertRequest_ProgressChanged(Google.Apis.Upload.IUploadProgress progress)
        {
            switch (progress.Status)
            {
                case UploadStatus.Uploading:
                    core.prog_up.Text = "{0} bytes sent." + progress.BytesSent;
                    break;

                case UploadStatus.Failed:
                    core.status.Text = "An error prevented the upload from completing.\n{0}" + progress.Exception;
                    core.status.ForeColor = System.Drawing.Color.Red;
                    break;
            }
        }

        void videosInsertRequest_ResponseReceived(Video video)
        {
            core.prog_up.Text = "Video id '{0}' was successfully uploaded." + video.Id;
        }
    }
}

后台工作者只是运行core();

当它到达函数时

 new UploadVideo().Run(articlename, file);

它开始上传,但又开始重复核心功能,因此在该视频上传之前生成另一个视频....如果我使用

new UploadVideo().Run(articlename, file).Wait();

然后程序只是停止并不确定地等待直到我关闭程序,我如何等待 Upload 类/方法完成,然后再继续核心方法中的 fore 循环?

对于回答的人,当我在新的上传之前添加等待时......它给了我:

严重性代码描述项目文件行抑制状态 错误 CS4033 'await' 运算符只能在异步中使用 方法。考虑用'async'修饰符标记这个方法和 将其返回类型更改为 '任务'。 articletoyoutube C:\Users\Laptop\Documents\Visual Studio 2017\Projects\articletoyoutube\articletoyoutube\Form1.cs 254 活动

【问题讨论】:

  • 啊哈-老-我如何同步调用异步方法。普遍接受的答案是“不要这样做” - 谷歌“同步调用异步方法”进行长时间讨论
  • 听起来你应该使用 Async/await
  • 我几乎 100% 确定 UploadVideo 中的 Form1 core = new Form1(); 是一个等待发生的错误,您永远不需要调用 new Form1() 您应该传递一个现有实例(这与解决你的问题)
  • 我同意。但是我试图在使用 getter 和 setter 之前让整个脚本正常工作,所以我至少知道它正在工作:P

标签: c# youtube youtube-api


【解决方案1】:

确保在您的方法中使用 async 关键字,并为任务使​​用 await 关键字。

例如:

private async Task core()
{ 
    // generate audio
    int i = 0;
    for (int n = 1; n < co; n++)
    {
        await generatevideo(image, articlename);
    }
}

private async Task generateVideo(string images, String articlename)
    {
       //generate the video here,
       try
            {
                var uploadVideo = new UploadVideo();
                await uploadVideo.Run(articlename, file);

            }
            catch (AggregateException ex)
            {
                foreach (var e in ex.InnerExceptions)
                {
                    ThreadSafe(() =>
                    {
                        this.Invoke((MethodInvoker)delegate
                        {
                            status.Text = e.Message;
                            status.ForeColor = System.Drawing.Color.Red;
                        });
                    });
                }
            }
    }

【讨论】:

    【解决方案2】:

    您需要使用await 一直使用您的调用堆栈到您的事件处理程序所在的位置,这将需要更改您的许多方法。

    private async Task core()
    { 
        // generate audio
        int i = 0;
        for (int n = 1; n < co; n++)
        {
            // generate video and upload to
            // youtube, this generates, but
            // when uploading to youtube this for
            // loop carries on when I want it to
            // upload to youtube first before carrying on
            await generatevideo(image, articlename);
        }
    }
    
    private async Task generateVideo(string images, String articlename)
    {
       //generate the video here, once done upload
       {code removed, this just generates a video, nothing important}
    
       // now upload (but I want it to finish before repeating the core() function
       try
            {
                await new UploadVideo().Run(articlename, file);
    
            }
            catch (AggregateException ex)
            {
                foreach (var e in ex.InnerExceptions)
                {
                    ThreadSafe(() =>
                    {
                        this.Invoke((MethodInvoker)delegate
                        {
                            status.Text = e.Message;
                            status.ForeColor = System.Drawing.Color.Red;
                        });
                    });
                }
            }
    }
    

    注意,使用 async/await 不适用于 BackgroundWorker,您需要切换到使用 Task.RunCancellationToken 以发出取消信号。

    Task _backgroundWork;
    CancellationTokenSource _cts;
    
    private void button2_Click(object sender, EventArgs e)
    {
        if (status.Text == "Stopped")
        {
            if (!generatearticle.IsBusy)
            {
                // started
                status.Text = "Started";
                status.ForeColor = System.Drawing.Color.Green;
                start.Text = "Stop Generating";
                _cts = new CancellationTokenSource();
                _backgroundWork = Task.Run(() => core(_cts.Token), _cts.Token);
            }
        }
        else
        {
            if(!_backgroundWork.IsCompleted)
            {
                _cts.Cancel();
                // started
                status.Text = "Stopped";
                status.ForeColor = System.Drawing.Color.Red;
                start.Text = "Start Generating";
            }
        }
    }
    

    【讨论】:

    • 感谢您的帮助,我收到 1 个错误,提示严重性代码描述项目文件行抑制状态错误 CS1501 方法“核心”没有重载需要 1 个参数 articletoyoutube C:\Users\Laptop\Documents \Visual Studio 2017\Projects\articletoyoutube\articletoyoutube\Form1.cs 93 活动
    • 是的,因为我将其更改为接收 CancellationToken,如果您希望您的代码可取消,则需要实施合作取消。 here is a good article 解释了您需要使用 CancellationToken 做什么。
    猜你喜欢
    • 1970-01-01
    • 2020-06-18
    • 2011-11-28
    • 2012-12-30
    • 1970-01-01
    • 2022-12-03
    • 1970-01-01
    • 2014-11-21
    • 1970-01-01
    相关资源
    最近更新 更多