首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Console.ReadLine()阻塞进程输出

Console.ReadLine()阻塞进程输出
EN

Stack Overflow用户
提问于 2017-01-23 22:45:42
回答 1查看 883关注 0票数 0

是否有更好的方法在控制台应用程序中取消长时间运行的任务?这段代码得到了简化,但与我的大型应用程序表现出了完全相同的问题。第一个方法Test1()只需要3秒,因为它阻塞了,但我希望能够取消它,因为GetStreamFromYoutubeDl方法将是一个更大的Task的一部分,它将无限运行。

由于某些原因,问题似乎存在于Console.ReadKey() -或读取方法的任何变体中,与读取进程的输出相冲突。在Test2()中可以很容易地看到这一点,如果你输入大约30次左右的按键,Task将立即打印它的输出。

添加TaskCreationOptions.LongRunning重载也不能解决我的问题。

包含完整的程序

代码语言:javascript
运行
复制
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace Testing
{
    class Program
    {
        static void Main(string[] args)
        {
            // Test 1 runs correctly, takes about 3 seconds
            //Test1();
            // Test 2 takes anywhere from 9 - 30 seconds, or hangs forever
            Test2();
        }

        static void Test()
        {
            var stopwatch = new Stopwatch();

            // This blocks, which makes it run correctly
            Task.Factory.StartNew(() => GetStreamFromYoutubeDl()).GetAwaiter().GetResult();

            Console.ReadLine();
        }

        static void Test2()
        {
            var cts = new CancellationTokenSource();

            var stopwatch = new Stopwatch();

            Task.Factory.StartNew(() => GetStreamFromYoutubeDl());

            Console.WriteLine("Press 'q' to exit.");
            while (true)
            {
                // Console.ReadKey here conflicts with the Process.StandardOutput.ReadLine for some reason, can confirm this
                // is the case as if you spam inputting keys, the process will output after ~30 or so key presses
                var read = Console.ReadKey(true);
                if (read.Key == ConsoleKey.Q)
                {
                    cts.Cancel();
                    break;
                }
            }
        }

        static void GetStreamFromYoutubeDl()
        {
            var stopwatch = new Stopwatch();
            var url = "https://www.youtube.com/watch?v=XbE1dL0iNkI";
            var youtubeDl = new ProcessStartInfo
            {
                FileName = "youtube-dl",
                // 
                Arguments = $"{url} -g -f bestaudio --audio-quality 0",
                RedirectStandardOutput = true,
                RedirectStandardError = false,
                CreateNoWindow = true,
                UseShellExecute = false
            };

            stopwatch.Start();
            var p = Process.Start(youtubeDl);

            if (youtubeDl == null)
            {
                Console.WriteLine("Unable to create youtube-dl process");
                return;
            }

            url = p.StandardOutput.ReadLine();

            stopwatch.Stop();
            Console.WriteLine(url + " " + stopwatch.Elapsed);
        }
    }
}
EN

回答 1

Stack Overflow用户

发布于 2019-03-07 20:55:46

基于您的示例:

代码语言:javascript
运行
复制
static void Test3()
{
    var cts = new CancellationTokenSource();
    var processingTask = Task.Factory.StartNew(() => GetStreamFromYoutubeDl(),cts.Token);
    var readingFromConsoleTask = Task.Factory.StartNew(() =>
    {
        Console.WriteLine("Press 'q' to exit.");
        while (true)
        {
            var read = Console.ReadKey(true);
            if (read.Key == ConsoleKey.Q)
            {
                cts.Cancel();
                return;
            }
        }
    });

    Task.WaitAny(processingTask, readingFromConsoleTask);
}

一旦发生以下任何一种情况,执行就会停止:要么处理任务结束,要么用户按'q‘退出。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41809016

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档