Reactive Extensions を試すことができるので、ユーザーが押したキーの IObservable を作成したいと思います。これどうやってするの?
これは C# コンソール アプリケーション用です。
Reactive Extensions を試すことができるので、ユーザーが押したキーの IObservable を作成したいと思います。これどうやってするの?
これは C# コンソール アプリケーション用です。
これを試して、読み取りキーの観測可能なシーケンスを取得してください。
IObservable<System.ConsoleKeyInfo> keys =
Observable
.Defer(() =>
Observable
.Start(() =>
Console.ReadKey()))
.Repeat();
これをテストしたところ、おやつのように機能しました。
ブロッキングバージョンのReadKey()には問題があり、サブスクリプションを破棄しても、キーを押すように求められます。
サブスクリプションを完全に解除したい場合、つまりプロンプトをキャンセルできるようにしたい場合は、(残念ながら)ポーリングアプローチを使用する必要があります。
Observable.Interval(TimeSpan.FromMilliseconds(100))
.Where(_ => Console.KeyAvailable)
.Select(_ => (char)Console.ReadKey(false).Key)
Amb
これで、このストリームのようなクールなことを実行Observable.Timer
して、キーを押すためのタイムアウトを設定できます。
キーの押下を非同期で読み取る方法がわからないためConsole.ReadKey()
、と一緒に別のスレッドで同期を使用する必要があると思いますSubject<T>
。何かのようなもの:
IObservable<ConsoleKeyInfo> ObserveKeysUntilEscape()
{
var keys = new Subject<ConsoleKeyInfo>();
Task.Run(
() =>
{
ConsoleKeyInfo key;
do
{
key = Console.ReadKey();
keys.OnNext(key);
} while (key.Key != ConsoleKey.Escape);
keys.OnCompleted();
});
return keys;
}
@svick の方法に代わる方法は、ReadKey
ループを として持ちEnumerable
、 に変換することObservable
です。これにより、バックグラウンドに配置されます。
static IEnumerable<ConsoleKeyInfo> KeyPresses()
{
ConsoleKeyInfo key;
do
{
key = Console.ReadKey();
yield return key;
} while (key.Key != ConsoleKey.Escape);
}
スレッド プールでオブザーバブルを生成できます。
var keys = KeyPresses().ToObservable(System.Reactive.Concurrency.Scheduler.ThreadPool);
keys.Subscribe(key => Console.WriteLine("Pressed: {0}", key.Key));
メイン スレッドでEscape
キーを待ちます。
keys.Where(key => key.Key == ConsoleKey.Escape).First();