Events Console.ReadLine()传递给C#事件
我正在学习RX,希望使用Console.ReadLine作为可观察序列的源 我知道我可以使用“收益率回报”创建“IEnumerable”,但对于我的具体用例,我决定创建一个C#事件,这样可能会有许多观察者能够共享相同的键盘输入 这是我的密码:Events Console.ReadLine()传递给C#事件,events,console,system.reactive,readline,Events,Console,System.reactive,Readline,我正在学习RX,希望使用Console.ReadLine作为可观察序列的源 我知道我可以使用“收益率回报”创建“IEnumerable”,但对于我的具体用例,我决定创建一个C#事件,这样可能会有许多观察者能够共享相同的键盘输入 这是我的密码: class Program { private delegate void OnNewInputLineHandler(string line); private static event OnNewInputLineHandler On
class Program
{
private delegate void OnNewInputLineHandler(string line);
private static event OnNewInputLineHandler OnNewInputLineEvent = _ => {};
static void Main(string[] args)
{
Task.Run((Action) GetInput);
var input = ConsoleInput();
input.Subscribe(s=>Console.WriteLine("1: " + s));
Thread.Sleep(30000);
}
private static void GetInput()
{
while (true)
OnNewInputLineEvent(Console.ReadLine());
}
private static IObservable<string> ConsoleInput()
{
return Observable.Create<string>(
(IObserver<string> observer) =>
{
OnNewInputLineHandler h = observer.OnNext;
OnNewInputLineEvent += h;
return Disposable.Create(() => { OnNewInputLineEvent -= h; });
});
}
}
有人能解释一下为什么会发生这种情况吗?你正试图让自己的生活变得困难。几乎总有一种方法可以让Rx变得简单。这只是学习从功能上而不是程序上思考的问题 这就是您所需要的:
class Program
{
static void Main(string[] args)
{
var subscription = ConsoleInput().Subscribe(s => Console.WriteLine("1: " + s));
Thread.Sleep(30000);
subscription.Dispose();
}
private static IObservable<string> ConsoleInput()
{
return
Observable
.FromAsync(() => Console.In.ReadLineAsync())
.Repeat()
.Publish()
.RefCount()
.SubscribeOn(Scheduler.Default);
}
}
类程序
{
静态void Main(字符串[]参数)
{
var subscription=ConsoleInput();
睡眠(30000);
subscription.Dispose();
}
专用静态IObservable控制台输入()
{
返回
可观察
.FromAsync(()=>Console.In.ReadLineAsync())
.重复
.Publish()
.RefCount()
.SubscribeOn(Scheduler.Default);
}
}
这允许多个订阅者通过
.Publish().RefCount()
共享一个输入。并且.SubscribeOn(Scheduler.Default)
将订阅推出到一个新线程,如果没有它,您将阻止订阅。如果您移动Task.Run((Action)GetInput)代码>订阅后,您的代码将按需要工作。这是因为在原始版本中,OnNewInputEvent(Console.ReadLine())
的第一次调用是在您将OnNewInputLineEvent连接到observer.OnNext
之前运行的,谢谢您的提示!但它并没有回答我的问题——为什么有一个版本可以工作:var s=Console.ReadLine();ONNEWINPUTLINEVENT(s);而另一个释放第一个通知:OnNewInputLineEvent(Console.ReadLine())@纳坦-我要猜一个比赛条件,但很难证明。生成的IL非常相似——只需先将字符串存储在变量中。可能只是需要更长的时间执行一些命令。对我来说似乎有点狡猾。这也是我的第一个想法。我也浏览了IL代码,不明白为什么会有不同。但如果这是一个比赛条件,它将不会如此一致!在调试和发布版本以及直接运行或在调试器中运行时,都是相同的行为。我想我需要构建RX并尝试调试,但我不确定这是否值得。回答不错。我认为主中的第一行有一个额外的括号,缺少一个分号。正确!这两个版本之间的区别在于,在var s=…
version中,GetInput挂起等待输入,并且在引用事件字段之前进行订阅。在短版本的事件(Console.ReadLine())
中,编译器首先复制事件字段的值(此时该值只有一个非Rx订户),然后调用ReadLine()
。即使订阅发生在输入第一个输入行之前,编译器使用的值也是前一个值。
class Program
{
static void Main(string[] args)
{
var subscription = ConsoleInput().Subscribe(s => Console.WriteLine("1: " + s));
Thread.Sleep(30000);
subscription.Dispose();
}
private static IObservable<string> ConsoleInput()
{
return
Observable
.FromAsync(() => Console.In.ReadLineAsync())
.Repeat()
.Publish()
.RefCount()
.SubscribeOn(Scheduler.Default);
}
}