简单的C#reactX示例阻止或具有竞争条件

时间:2018-08-03 10:25:56

标签: c# .net system.reactive

观看后: https://www.youtube.com/watch?v=Bme_RiT9CK4 我正在尝试使用C#和reactX复制示例。总之,这是一个货币转换器。用户指定他们想要的货币的数量和类型。当前汇率是从服务器检索的,将花费可变的时间来返回。由于服务器时间的可变性,较旧的货币请求有可能在较新的货币请求之后出现。该警告被用作使事物具有反应性的动机,从而避免出现竞争状况错误。我可以通过在Task上使用Wait()代表货币汇率来避免反应式代码中的竞争状况,但这会阻塞GUI。我应该如何处理呢?也许我应该取消其他任务?以下是我的代码,它不会阻塞但存在竞争条件问题。

        public CurrencyWindow()
    {
        InitializeComponent();

        var amount = Observable.FromEventPattern<TextChangedEventArgs>(txtAmount, "TextChanged").Select(t=>int.Parse(txtAmount.Text));

        var yen = Observable.FromEventPattern<RoutedEventArgs>(rdoYen, "Checked").Select(t => "Yen");
        var dollar = Observable.FromEventPattern<RoutedEventArgs>(rdoDollar, "Checked").Select(t => "Dollar");
        var pound = Observable.FromEventPattern<RoutedEventArgs>(rdoPound, "Checked").Select(t => "Pound");

        // merge the currency selection into one stream.
        var currencyType = yen.Merge(dollar).Merge(pound);

        // Lets now get a stream of currency rates.
        var exchangeRate = currencyType.Select(s => GetExchangeRate(s));


        amount.CombineLatest(exchangeRate, async (i, d) => i * await d).Subscribe(async v =>
        {
            var val = await v;
            txtCost.Text = val.ToString();
        });
    }

    private Task<double> GetExchangeRate(string currency)
    {
        double exchange = 0;
        switch(currency)
        {
            case "Yen":
                exchange = 1;
                break;
            case "Pound":
                exchange = 2;
                break;
            case "Dollar":
                exchange = 3;
                break;
        }

        return Task.Factory.StartNew(() => 
        {
            System.Threading.Thread.Sleep((int)exchange * 3000);
            return exchange;
        });
    }

1 个答案:

答案 0 :(得分:0)

使用此代码,看看它是否有效:

var exchangeRate = currencyType
    .Select(s => Observable.FromAsync(() => GetExchangeRate(s)))
    .Switch();

amount
    .CombineLatest(exchangeRate, (i, d) => i * d)
    .Subscribe(v =>
    {
        var val = v;
        txtCost.Text = val.ToString();
    });

此代码将确保只有最新生成的currencyType才会返回汇率。如果使用了新的货币,则之前所有对GetExchangeRate的机上通话都将被忽略(即使它们是在当前货币之后输入的)。