這里我有用C#撰寫的簡單代碼。
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Reactive.Subjects;
namespaceReactiveProgramming
{
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("
" new string(' ', Console.WindowWidth) "
")。)
});
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("
" new string(' ', Console.WindowWidth) "
"......它可以作業,并在螢屏上一個接一個地列印所有的數字,但我想在上面列印......
但是如果我把我的主函式改成這樣:
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("
" new string(' ', Console.WindowWidth) "
");
});
generateSeq.Run()。
}
在我評論這兩行的地方......輸出如下......
但是,我想在同一位置列印輸出,而不是像第二張圖片那樣按順序輸出。只要把新的輸出寫在舊的輸出上就可以了
注意:我想在同一位置列印輸出。
注意:我在 Macbook Pro (Big Sur) 上運行它,它發生在 .net core 3.1 或 .net 5.0 上,并使用 iTerm 作為控制臺模擬器
我在 Macbook Pro (Big Sur) 上運行它,它發生在 .net core 3.1 或 .net 5.0 上,并使用 iTerm 作為控制臺模擬器
uj5u.com熱心網友回復:
如果是我來寫,我會采用這樣的實作方式:
static async 任務 Main(string[] args)
{
Console.WriteLine("Hello World!")。
IObservable<System.ConsoleKeyInfo> keys =
可觀察的
.Start(() => Console.ReadKey())。
await
觀察者
.Interval(TimeSpan.FromSeconds(1.0)
.Take(10)
.TakeUntil(keys)
.Do(x =>
{
Console.WriteLine(x);
Console.SetCursorPosition(0, Console.CursorTop - 1) 。
},
() => Console.SetCursorPosition(0, Console.CursorTop 1) )。
Console.WriteLine("再見世界!")。
}
在可能的情況下,你應該避免使用主題。
uj5u.com熱心網友回復:
SetCursorPosition在不被其他執行緒呼叫的情況下作業得非常好。你可以使用異步方法來解決這個問題,而不是使用Task.Run
class Program<
{
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) 。
});
//啟動后臺操作 classGenerateSequence
{
public readonly Subject<int> Sequence = new()。
public void Run(int runTimes = 10)
{
ConsoleKeyInfo cki;
///創建一個取消令牌,因為如果用戶按
//Escape鍵,我們就不需要運行我們的后臺任務。
//不再需要,任務應該被停止。
var tokenSource = new CancellationTokenSource()。
var token = tokenSource.Token。
//我們不能在這里使用await關鍵字,因為我們需要。
///監聽ReadKey函式,以防用戶想要。
//停止執行。如果沒有await,任務將在中運行。
//后臺異步地運行。
var task = RunForTimes(runTimes,token);
//等待Escape鍵來取消執行或停止執行
//如果它已經在運行。
do
{
cki = Console.ReadKey()。
} while (cki.Key != ConsoleKey.Escape && !task.IsCompleted) 。
//span>如果后臺任務沒有完成,就取消它。
if (!task.IsCompleted)
tokenSource.Cancel()。
//將CursorPosition恢復到原始狀態。
Console.SetCursorPosition(0, Console.CursorTop 1) 。
Console.WriteLine("執行結束")。
}
//我們使用一個異步任務而不是一個void來運行我們的后臺。
//job Asynchronously.
//主要的區別是,我們不應該使用一個單獨的執行緒。
//因為我們需要在主執行緒上安全地訪問Console(讀或寫)。
private async Task RunForTimes(int runTimes, CancellationToken token)。
{
for (var i = 0; i < runTimes; i )
{
//取消操作,如果它被請求。
if (token.IsCancellationRequested) return;
Sequence.OnNext(i);
await Task.Delay(1000, token);
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/308317.html
標籤:
上一篇:如何在VB.NET/WinForms中實作可搜索的資料結構?(核心3.1)
下一篇:Java中懸空和調度器的競賽條件



