【发布时间】:2015-04-27 07:50:33
【问题描述】:
我正在从 Rx 向网络写入数据。当然,我会在订阅结束时使用Finally 关闭我的流。这在OnError() 和OnComplete() 上都可以正常工作。 Rx 将依次运行OnNext() ... OnNext()、OnComplete()、Finally()。
但是,有时我想提前终止序列,为此我使用Dispose()。不知何故,Finally() 现在与最后一个OnNext() 调用并行运行,导致在OnNext() 中仍然写入流时出现异常,以及写入不完整。
我的订阅大致如下:
NetworkStream stm = client.GetStream();
IDisposable disp = obs
.Finally(() => {
client.Close();
})
.Subscribe(d => {
client.GetStream().Write(d.a, 0, d.a.Lenght);
client.GetStream().Write(d.b, 0, d.b.Lenght);
} () => {
client.GetStream().Write(something(), 0, 1);
});
Thread.sleep(1000);
disp.Dispose();
我也尝试了替代方法,CancellationToken。
如何正确取消订阅?我不介意它是否跳过OnComplete(),只要Finally() 仍在运行。但是,并行运行Finally() 是有问题的。
我也觉得应该有一种更好的方法来管理资源,将声明移到序列中,这将是一个更好的解决方案。
编辑:以下代码更清楚地显示了问题。我希望它总是打印 true,相反,它经常给出 false,表明 Dispose 在最后一个 OnNext 之前结束。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Try finally");
for (int i = 0; i < 10; i++)
{
Finally();
}
Console.WriteLine("Try using");
for (int i = 0; i < 10; i++)
{
Using();
}
Console.WriteLine("Try using2");
for (int i = 0; i < 10; i++)
{
Using2();
}
Console.ReadKey();
}
private static void Using2()
{
bool b = true, c = true, d;
var dis = Disposable.Create(() => c = b);
IDisposable obDis = Observable.Using(
() => dis,
_ => Observable.Create<Unit>(obs=>
Observable.Generate(0,
i => i < 1000,
i => i + 1,
i => i,
i => TimeSpan.FromMilliseconds(1)
).Subscribe(__ => { b = false; Thread.Sleep(100); b = true; })))
.Subscribe();
Thread.Sleep(15);
obDis.Dispose();
d = b;
Thread.Sleep(101);
Console.WriteLine("OnDispose: {1,5} After: {2,5} Sleep: {0,5}", b, c, d);
}
private static void Using()
{
bool b = true, c = true, d;
var dis = Disposable.Create(() => c = b);
IDisposable obDis = Observable.Using(
() => dis,
_ => Observable.Generate(0,
i => i < 1000,
i => i + 1,
i => i,
i => TimeSpan.FromMilliseconds(1)
)).Subscribe(_ => { b = false; Thread.Sleep(100); b = true; });
Thread.Sleep(15);
obDis.Dispose();
d = b;
Thread.Sleep(101);
Console.WriteLine("OnDispose: {1,5} After: {2,5} Sleep: {0,5}", b, c, d);
}
private static void Finally()
{
bool b = true, c = true, d;
IDisposable obDis = Observable.Generate(0,
i => i < 1000,
i => i + 1,
i => i,
_ => DateTime.Now.AddMilliseconds(1)
)
.Finally(() => c = b)
.Subscribe(_ => { b = false; Thread.Sleep(100); b = true; });
Thread.Sleep(15);
obDis.Dispose();
d = b;
Thread.Sleep(101);
Console.WriteLine("OnDispose: {1,5} After: {2,5} Sleep: {0,5}", b, c, d);
}
}
}
【问题讨论】:
标签: c# system.reactive