3

Reactive Extensions を試すことができるので、ユーザーが押したキーの IObservable を作成したいと思います。これどうやってするの?

これは C# コンソール アプリケーション用です。

4

4 に答える 4

4

これを試して、読み取りキーの観測可能なシーケンスを取得してください。

        IObservable<System.ConsoleKeyInfo> keys =
            Observable
                .Defer(() =>
                    Observable
                        .Start(() =>
                            Console.ReadKey()))
                .Repeat();

これをテストしたところ、おやつのように機能しました。

于 2012-05-21T00:18:42.323 に答える
3

ブロッキングバージョンのReadKey()には問題があり、サブスクリプションを破棄しても、キーを押すように求められます。

サブスクリプションを完全に解除したい場合、つまりプロンプトをキャンセルできるようにしたい場合は、(残念ながら)ポーリングアプローチを使用する必要があります。

Observable.Interval(TimeSpan.FromMilliseconds(100))
          .Where(_ => Console.KeyAvailable)
          .Select(_ => (char)Console.ReadKey(false).Key)

Ambこれで、このストリームのようなクールなことを実行Observable.Timerして、キーを押すためのタイムアウトを設定できます。

于 2012-05-22T09:48:16.943 に答える
0

キーの押下を非同期で読み取る方法がわからないため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;
}
于 2012-05-20T19:23:28.283 に答える
0

@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();
于 2012-05-21T00:19:29.090 に答える