你如何使用Rx请求用户输入?

时间:2016-09-25 14:09:18

标签: c# system.reactive

我正在编写一个类,它封装了一个状态机,代表我的应用程序尝试与我自己的Web服务进行通信。基本状态是断开连接,连接,连接和需要凭据。我想过使用Rx通过BehaviorSubject发布状态更改的良好学习经验(希望这本身就是好的用法?)。我对此主题的一个状态是“需要凭证”,我需要在继续之前提示用户提供用户名和密码。出于本练习的目的,我们假设该类托管在Windows控制台应用程序中,并且我想提示用户

Console.WriteLine("Enter username");
var userName = Console.ReadLine();
Console.WriteLine("Enter password");
var password = Console.ReadLine();

由于我的Rx BehaviorSubject达到状态'RequiresCredentials',每次遇到此状态时都应该点击此状态。

我已将BehaviorSubject公开为自身(即未将其隐藏在Observable接口或其他任何内容之后)

public BehaviorSubject<ConnectionState> State { get; }

并希望这个凭据请求被阻止。

我应该使用什么过程正确订阅此主题,等待此输入​​并最终将控制权返回给调用线程?

1 个答案:

答案 0 :(得分:2)

如果您不使用任务或等待,或任何异步,Rx订阅代码将在同一个线程上观察,并在您使用阻止代码时阻止。如果您不关心输入,那么您可以直接Subscribe。如果您想使用输入的用户名/密码,则可以使用Select。所以这会奏效:

class Program
{
    static void Main(string[] args)
    {
        var subject = new BehaviorSubject<ConnectionState>(ConnectionState.Disconnected);

        var getCredentials = subject.Where(cs => cs == ConnectionState.RequiresCredentials)
            .Select(cs =>
            {
                Console.WriteLine("Enter username");
                var userName = Console.ReadLine();
                Console.WriteLine("Enter password");
                var password = Console.ReadLine();
                return Tuple.Create(userName, password);
            });
        using (var subscription = getCredentials.Subscribe())
        {
            Console.WriteLine("Changing to Connecting...");
            subject.OnNext(ConnectionState.Connecting);
            Console.WriteLine("Changing to RequiresCredentials...");
            subject.OnNext(ConnectionState.RequiresCredentials);
            Console.WriteLine("Connected.");
            subject.OnNext(ConnectionState.Connected);
        }

    }
}

enum ConnectionState
{
    Disconnected,
    Connected,
    Connecting,
    RequiresCredentials
}

它产生以下输出:

Changing to Connecting...
Changing to RequiresCredentials...
Enter username
ThisIsMyUserName
Enter password
ThisIsMyPassword
Connected.

这是对Rx的一种相当向后的使用:如果您希望以迭代,程序的方式使用Rx,为什么不使用C#来节省自己的复杂性?