【发布时间】:2021-11-10 04:40:45
【问题描述】:
这里我有用 C# 编写的简单代码。
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Reactive.Subjects;
namespace ReactiveProgramming
{
class Program
{
static void Main(string[] args)
{
var generateSeq = new GenerateSequence();
Console.WriteLine("Hello World!");
generateSeq.Sequence.Subscribe(val =>
{
Console.WriteLine(val);
// it works if I remove below two lines ...
Console.SetCursorPosition(0, Console.CursorTop - 1);
Console.Write("\r" + new string(' ', Console.WindowWidth) + "\r");
});
generateSeq.Run();
}
}
class GenerateSequence
{
public Subject<int> Sequence = new Subject<int>();
public void Run(int runTimes = 10)
{
ConsoleKeyInfo cki;
Task.Run(() => runForTimes(10));
do
{
cki = Console.ReadKey();
} while (cki.Key != ConsoleKey.Escape);
}
public void runForTimes(int runTimes = 10)
{
for (var i = 0; i < 10; i++)
{
Sequence.OnNext(i);
Thread.Sleep(1000);
}
}
}
}
但不是在彼此之上打印序列,而是在第一次发出后冻结输出。
并且在 Linux 中也进行了测试...同样的输出。
如果我将这些行 Console.SetCursorPosition 和 Console.Write("\r" + new string(' ', Console.WindowWidth) + "\r") 从订阅远程...
但是如果我像这样更改我的 Main 函数:
static void Main(string[] args)
{
var generateSeq = new GenerateSequence();
Console.WriteLine("Hello World!");
generateSeq.Sequence.Subscribe(val =>
{
Console.WriteLine(val);
// Console.SetCursorPosition(0, Console.CursorTop - 1);
// Console.Write("\r" + new string(' ', Console.WindowWidth) + "\r");
});
generateSeq.Run();
}
我已经评论了这两行...输出如下...
但不是像第二张图像那样按顺序输出,我想在同一位置打印输出。只需将新输出覆盖旧输出即可
注意:我在 Macbook Pro (Big Sur) 上运行它,它使用 .net core 3.1 或 .net 5.0 并使用 iTerm 作为控制台模拟器
【问题讨论】:
-
您可能想重新阅读minimal reproducible example...您是否认为这是线程问题还是只是SetCursorPosition?在这两种情况下都不需要所有花哨的代码......
-
这与您的问题无关,但总的来说 Task.Delay() 比 Thread.Sleep() 更好。 await Task.Delay 会在您的代码中导致逻辑暂停,但保持线程空闲以进行其他活动,thread.sleep 会导致线程无法被任何人使用。
-
@AlexeiLevenkov 对于这个特定场景来说,这是最小的生产......
-
@AliReza 太棒了...效果很好...非常感谢您抽出宝贵的时间来研究它...
-
你为什么不使用
Observable.Interval(TimeSpan.FromSeconds(1.0)).Take(10)来生成你的序列?
标签: c# multithreading .net-core system.reactive reactive