是否有更好的方法在控制台应用程序中取消长时间运行的任务?这段代码得到了简化,但与我的大型应用程序表现出了完全相同的问题。第一个方法Test1()只需要3秒,因为它阻塞了,但我希望能够取消它,因为GetStreamFromYoutubeDl方法将是一个更大的Task的一部分,它将无限运行。
由于某些原因,问题似乎存在于Console.ReadKey() -或读取方法的任何变体中,与读取进程的输出相冲突。在Test2()中可以很容易地看到这一点,如果你输入大约30次左右的按键,Task将立即打印它的输出。
添加TaskCreationOptions.LongRunning重载也不能解决我的问题。
包含完整的程序
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);
}
}
}发布于 2019-03-07 20:55:46
基于您的示例:
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‘退出。
https://stackoverflow.com/questions/41809016
复制相似问题