是否有更好的方法可以在控制台应用程序中取消长时间运行的任务?此代码已简化,但与我的大型应用程序具有相同的问题。第一种方法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);
}
}
}
答案 0 :(得分:0)
根据您的示例:
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”退出。