.net 反应式扩展(Rx)和异步类
我在这篇文章中读到:“不鼓励使用EBAP。使用新的Rx扩展(类似于msdn的PrimeNumberCalculator示例)设计异步组件的最佳方法是什么 先谢谢你 更新 我设法写了我自己的素数计算器,我想听听你的意见:.net 反应式扩展(Rx)和异步类,.net,asynchronous,system.reactive,iasyncresult,.net,Asynchronous,System.reactive,Iasyncresult,我在这篇文章中读到:“不鼓励使用EBAP。使用新的Rx扩展(类似于msdn的PrimeNumberCalculator示例)设计异步组件的最佳方法是什么 先谢谢你 更新 我设法写了我自己的素数计算器,我想听听你的意见: using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Threading; namespace ConsoleAppli
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace ConsoleApplication13
{
public class PrimeNumberCalculator
{
private readonly Subject<int> primeSubject;
private IDisposable currentSubscription;
public PrimeNumberCalculator()
{
primeSubject = new Subject<int>();
Primes = primeSubject.Hide();
}
public IObservable<int> Primes{ get; private set; }
/// <summary>
/// Determine if n is prime.
/// </summary>
private static bool IsPrime(ArrayList primes, int n, out int firstDivisor)
{
bool foundDivisor = false;
bool exceedsSquareRoot = false;
int i = 0;
firstDivisor = 1;
// Stop the search if:
// there are no more primes in the list,
// there is a divisor of n in the list, or
// there is a prime that is larger than
// the square root of n.
while ( (i < primes.Count) && !foundDivisor && !exceedsSquareRoot)
{
// The divisor variable will be the smallest
// prime number not yet tried.
int divisor = (int)primes[i++];
// Determine whether the divisor is greater
// than the square root of n.
if (divisor * divisor > n)
{
exceedsSquareRoot = true;
}
// Determine whether the divisor is a factor of n.
else if (n % divisor == 0)
{
firstDivisor = divisor;
foundDivisor = true;
}
}
return !foundDivisor;
}
/// <summary>
/// Itereates from 1 to numberToTest and returns all primes.
/// </summary>
private IEnumerable<int> PrimeNumberIterator(int numberToTest)
{
var primes = new ArrayList();
var n = 5;
// Add the first prime numbers.
primes.Add(2);
primes.Add(3);
// Do the work.
while (n < numberToTest)
{
int firstDivisor;
if (IsPrime(primes, n, out firstDivisor))
{
// Report to the client that a prime was found.
yield return n;
Thread.Sleep(5000); //simulate long running task.
primes.Add(n);
}
// Skip even numbers.
n += 2;
}
}
/// <summary>
/// Begin a prime number exploration.
/// If there is some exploration in progress unsubscribe.
/// </summary>
public void IsPrime(int numberToTest)
{
if (currentSubscription != null) currentSubscription.Dispose();
currentSubscription = PrimeNumberIterator(numberToTest)
.ToObservable()
.Subscribe(primeSubject.OnNext);
}
/// <summary>
/// Cancel a prime number exploration
/// </summary>
public void Cancel()
{
if (currentSubscription != null) currentSubscription.Dispose();
}
}
internal class Program
{
private static void Main(string[] args)
{
var primeNumberCalculator = new PrimeNumberCalculator();
primeNumberCalculator.Primes.Subscribe(p => Console.WriteLine("Is prime {0}", p));
var exit = false;
do
{
Console.WriteLine("Write a number to explore and press enter: ");
var input = Console.ReadLine();
int primeToExplore;
if(int.TryParse(input, out primeToExplore))
{
primeNumberCalculator.IsPrime(primeToExplore);
}
else {
primeNumberCalculator.Cancel();
exit = true;
}
} while (!exit);
}
}
}
使用系统;
使用系统集合;
使用System.Collections.Generic;
使用System.Linq;
使用系统线程;
命名空间控制台应用程序13
{
公共类素数计算器
{
私人只读主题;
私人IDisposable当前订阅;
公共素数计算器()
{
primeSubject=新主题();
Primes=primeSubject.Hide();
}
公共IObservable素数{get;private set;}
///
///确定n是否为素数。
///
私有静态bool-IsPrime(数组列表素数,int n,out int第一除数)
{
bool foundDivisor=false;
bool EXCEDSQUEROOT=假;
int i=0;
第一除数=1;
//如果出现以下情况,请停止搜索:
//列表中没有更多的素数,
//列表中有n的除数,或
//有一个素数大于
//n的平方根。
而((in)
{
exceedsSquareRoot=真;
}
//确定除数是否为n的因子。
else if(n%除数==0)
{
第一除数=除数;
foundDivisor=true;
}
}
return!foundDivisor;
}
///
///它从1到numberToTest创建并返回所有素数。
///
专用IEnumerable PrimeNumberItemerator(整数测试)
{
var primes=新的ArrayList();
var n=5;
//加上第一个素数。
添加(2);
添加(3);
//做这项工作。
while(nConsole.WriteLine(“Is prime{0}”,p));
var exit=false;
做
{
Console.WriteLine(“写一个要浏览的数字,然后按enter:”);
var input=Console.ReadLine();
int primeToExplore;
if(int.TryParse(输入、输出primeToExplore))
{
primeNumberCalculator.IsPrime(primeToExplore);
}
否则{
primeNumberCalculator.Cancel();
退出=真;
}
}同时(!退出);
}
}
}
这里有一种方法,使用可变状态:
int lastPrime = 0; // or starting prime
IObservable<int> Primes =
Observable.Defer(() =>
{
do
{
lastPrime++;
} while (!IsPrime(lastPrime));
return Observable.Return(lastPrime);
}).Repeat();
var disp = Primes.Where(p => p < 1000000).Subscribe(Console.WriteLine);
/// ...
disp.Dispose();
int lastPrime=0;//还是开始质数
可观测素数=
可观察。延迟(()=>
{
做
{
lastPrime++;
}而(!IsPrime(lastPrime));
可观察的返回。返回(lastPrime);
}).重复();
var disp=Primes.Where(p=>p<1000000).Subscribe(Console.WriteLine);
/// ...
disp.Dispose();
谢谢,看起来不错!!取消怎么样?(如msdn中的示例)谢谢,这正是我想要的。传递给Defer的函数不是纯函数。这意味着代码不能在没有问题的情况下并发运行,并且接收结果是不可预测的。您可以在lastPrime上同步,但这也是一个坏主意(仍然不是一个纯函数)。解决方案是将一个纯函数装箱。如果我在这里错了,请纠正我:)您可能应该使用scan()来携带状态。