如何阻止控制台暂停我的线程和任务
本文关键字:线程 任务 我的 暂停 何阻止 控制台 | 更新日期: 2023-09-27 18:32:55
当我在控制台窗口中使用滚动条时,所有线程和任务都会暂停。有什么方法可以防止这种情况发生吗?
例:
Task.Run(async () =>
{
for (var z = 0; true; z++)
{
Console.WriteLine(z);
await Task.Delay(200);
}
});
或
var s = new Thread(() =>
{
for (var z = 0; true; z++)
{
Console.WriteLine(z);
Thread.Sleep(200);
}
});
如果将这些代码示例中的任何一个作为控制台应用程序运行,则两者都将执行相同的操作:打印一些数字。在执行过程中,用鼠标左键按住滚动条一段时间,数字将停止出现。任务/线程已暂停。当您释放鼠标按钮时,数字将继续。
由于滚动条发布后的数字紧随之前的数字,因此控制台并没有简单地停止数字的输出。它一直在 Console.WriteLine - 方法中等待,直到释放滚动条。
有谁知道如何解决我的问题?
你无能为力来阻止这种情况。 Console.WriteLine
按住滚动条时会阻塞,这与线程或任务完全无关。下面的小程序显示了同样的问题。
using System;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
for (var z = 0; true; z++)
{
Console.WriteLine(z);
Thread.Sleep(200);
}
}
}
}
您无法更改 Console.WriteLine
的行为,您唯一能做的就是在您和写入控制台之间放置一个缓冲区。
using System;
using System.Collections.Concurrent;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//The writer lives in another thread.
var s = new Thread(ConsoleWriter);
s.Start();
for (var z = 0; true; z++)
{
//This add call does not get blocked when Console.WriteLine gets blocked.
LinesToWrite.Add(z.ToString());
Thread.Sleep(200);
}
}
static void ConsoleWriter()
{
foreach (var line in LinesToWrite.GetConsumingEnumerable())
{
//This will get blocked while you hold down the scroll bar but
// when you let go it will quickly catch up.
Console.WriteLine(line);
}
}
static readonly BlockingCollection<string> LinesToWrite = new BlockingCollection<string>();
}
}
这只是一个快速而肮脏的解决方案,还有其他方法可以解决这个问题以使其更加透明,例如制作一个从TextWriter
派生的类来缓冲调用并在调用Console.SetOut(
中使用该类。
如果您不希望代码在锁定对控制台的访问时阻止(在本例中为用户),并且不要等待该异步操作完成再继续,则需要异步写入控制台。 这可以像使用 Task.Run(() => Console.WriteLine(z))
代替 Console.WriteLine(z)
一样简单。
你还需要复制(在调用Run
之前)任何闭合变量,这些变量在调用Task.Run
后最终会发生变化,因为闭包在变量而不是值上闭合。
也就是说,这强烈表明您应该在这里重新考虑您的设计。 也许控制台不是您输出数据的正确方式;另一种类型的 UI 可能是合适的。