我正在开发一个Xamarin应用程序,我已经扩展了
Connectivity插件以使用Rx而不是事件.
我的目标是在重新建立连接时引入一点延迟,以允许网络适配器有时间连接到互联网(UWP的解决方法).如果在此延迟中出现任何值,则只需保留最后一个值,因为只有当前连接状态很重要.
这很好,但感觉有点hacky:
internal static class ConnectivityExtensions
{
public static IObservable<bool> ToObservable(this IConnectivity @this)
{
var connectivity = Observable
.FromEventPattern<ConnectivityChangedEventHandler, ConnectivityChangedEventArgs>(
handler => @this.ConnectivityChanged += handler,
handler => @this.ConnectivityChanged -= handler)
.Select(args => args.EventArgs.IsConnected);
var sampling = connectivity
.Timestamp()
.Select(ts => new
{
ts.Value,
ts.Timestamp,
// If reconnection, delay subscriber notification for 250ms
DelayUntil = ts.Value ? (DateTimeOffset?)ts.Timestamp.Add(TimeSpan.FromMilliseconds(250)) : null
})
.Scan((acc, current) => new
{
current.Value,
current.Timestamp,
// If current notification is during reconnection notification delay period, delay the current notification too
DelayUntil = current.Timestamp < acc.DelayUntil ? acc.DelayUntil : current.DelayUntil
})
// Perform reconnection delay
.Delay(x => x.DelayUntil.HasValue
? Observable.Return(x.DelayUntil.Value).Delay(x.DelayUntil.Value)
: Observable.Empty<DateTimeOffset>())
// All delayed notifications are delayed until the same time, so we only need one notification to trigger sampling after delay
.DistinctUntilChanged()
.Select(_ => Unit.Default);
return connectivity
.Sample(sampling)
.StartWith(@this.IsConnected)
.DistinctUntilChanged()
.Replay(1)
.RefCount();
}
}
示例输出:
通过这个例子,你可以看到我正在做的事情的好处.当“连接”改变时,延迟阻止订户处理数据,但是尚未建立互联网连接(UWP).此外,这还可以保护用户免受任何快速“开/关”通知.
// StartsWith: True
ConnectivityChanged(null, new ConnectivityChangedEventArgs { IsConnected = true }); // Delay 250ms
Thread.Sleep(TimeSpan.FromMilliseconds(250)); // Sample: True, Ignored due to DistinctUntilChanged
ConnectivityChanged(null, new ConnectivityChangedEventArgs { IsConnected = false }); // Sample: False
Thread.Sleep(TimeSpan.FromMilliseconds(250));
ConnectivityChanged(null, new ConnectivityChangedEventArgs { IsConnected = true }); // Delay 250ms, Discarded due to Sample
ConnectivityChanged(null, new ConnectivityChangedEventArgs { IsConnected = false }); // Delayed by previous, Discarded due to Sample
ConnectivityChanged(null, new ConnectivityChangedEventArgs { IsConnected = true }); // Delayed by previous, Discarded due to Sample
ConnectivityChanged(null, new ConnectivityChangedEventArgs { IsConnected = false }); // Delayed by previous
Thread.Sleep(TimeSpan.FromMilliseconds(250)); // Sample: False, Ignored due to DistinctUntilChanged
ConnectivityChanged(null, new ConnectivityChangedEventArgs { IsConnected = true }); // Delay 250ms, Discarded due to Sample
ConnectivityChanged(null, new ConnectivityChangedEventArgs { IsConnected = false }); // Delayed by previous
Thread.Sleep(TimeSpan.FromMilliseconds(250)); // Sample: False, Ignored due to DistinctUntilChanged
// Final Output:
// True
// False
有没有更优化的方法来实现这种类型的延迟采样?
最佳答案 如果我理解正确,这是一个大理石图,说明事情将如何解决:
T (millis) : 0----250--500--1000-1250-1500-1750-2000
Connectivity : ---F-------T---F----T-------F--T-------
ScanValueDelayUntil : ---null----800-null-1500----null2100---
Sampling : -------------x-----------x-----------x-
ResultSampled : T------------T-----------T-----------T-
ResultSampledDistinct: T--------------------------------------
这似乎没有多大意义.你能描述一下你希望结果代表什么,或者纠正我错在哪里?