[英]Use an RX observable to create a “debounce” effect
I've got an FTP client that I want to leave connected to the FTP server, unless (say) a minute passes with no activity. 我有一个FTP客户端,我想要连接到FTP服务器,除非(比方说)一分钟没有活动。 I'd like to do this using an Observable.
我想使用Observable来做这件事。
Here's a very dumbed-down Linqpad script that demonstrates the concept: 这是一个非常愚蠢的Linqpad脚本,演示了这个概念:
async Task Main()
{
var client = new Client();
client.Connect();
var debounce = new Subject<int>();
debounce
.Throttle(TimeSpan.FromSeconds(1))
.Subscribe(eventNumber => client.Disconnect(eventNumber));
// Something uses the FTP client
debounce.OnNext(1);
await Task.Delay(200);
// Something else uses the FTP client
debounce.OnNext(2);
await Task.Delay(300);
// No activity, the client will disconnect
await Task.Delay(1000);
}
public class Client
{
public void Connect() => Console.WriteLine("Connected");
public void Disconnect(int eventNumber) => Console.WriteLine($"Disconnected: {eventNumber}");
}
This works perfectly - the client disconnects after event "2". 这很有效 - 客户端在事件“2”之后断开连接。
Question : Is there a better way to do this? 问题 :有更好的方法吗? Or more accurately, is there a better way to do this without using the
Subject
? 或者更准确地说,如果不使用
Subject
,有没有更好的方法呢?
Here's a more fleshed-out version of the class - effectively, it is subscribed to an observable which will tell it some files that need to be downloaded; 这是一个更加充实的类本 - 有效地,它订阅了一个observable,它会告诉它一些需要下载的文件; if no files come through for some timeout, then I want the client to disconnect.
如果没有文件通过一些超时,那么我希望客户端断开连接。
public class MyClassThatDownloadsViaFtp
{
private IObserver<Unit> _debouncer;
private FtpClient _client;
public MyClassThatDownloadsViaFtp(IObservable<FileToDownload> filesToDownloadViaFtp)
{
filesToDownloadViaFtp.Subscribe(DownloadFileViaFtp);
// Disconnect after a minute of activity
_debouncer = new Subject<Unit>();
_debouncer
.Throttle(TimeSpan.FromMinutes(1))
.Subscribe(_ => DisconnectFtpClient());
}
public void DownloadFileViaFtp(FileToDownload file)
{
if (_client == null) _client = ConnectFtpClient();
// Signal that the client is doing some work to prevent disconnect
_debouncer.OnNext(Unit.Default);
_client.Download(file.PathOnFtpServer);
}
// implementation irrelivent
private FtpClient ConnectFtpClient() => new FtpClient();
private FtpClient DisconnectFtpClient() => _client = null;
}
I figured out that since I have a source stream, it's probably easier to throttle it to achieve the same effect (as follows); 我想通了,因为我有一个源流,它可能更容易限制它以达到相同的效果(如下); however, I'd still like to know the best way to do this in cases where I do not have a source stream that I can throttle.
但是,在我没有可以限制的源流的情况下,我仍然想知道最好的方法。
public class MyClassThatDownloadsViaFtp
{
private FtpClient _client;
public MyClassThatDownloadsViaFtp(IObservable<FileToDownload> filesToDownloadViaFtp)
{
filesToDownloadViaFtp
.Select(DownloadFileViaFtp)
.Throttle(TimeSpan.FromMinutes(1))
.Subscribe(_ => DisconnectFtpClient());
}
public Unit DownloadFileViaFtp(FileToDownload file)
{
if (_client == null) _client = ConnectFtpClient();
_client.Download(file.PathOnFtpServer);
return Unit.Default;
}
// implementation irrelivent
private FtpClient ConnectFtpClient() => new FtpClient();
private FtpClient DisconnectFtpClient() => _client = null;
}
You basically answered your question with this: 你基本上回答了你的问题:
public MyClassThatDownloadsViaFtp(IObservable<FileToDownload> filesToDownloadViaFtp)
{
filesToDownloadViaFtp
.Select(DownloadFileViaFtp)
.Throttle(TimeSpan.FromMinutes(1))
.Subscribe(_ => DisconnectFtpClient());
}
If you don't have a convenient stream like filesToDownloadViaFtp
then create one from either Observable.Create
or Observable.FromEvent
, or Observable.FromEventPattern
, etc.. 如果你没有像
filesToDownloadViaFtp
这样的方便的流,那么从Observable.Create
或Observable.FromEvent
或Observable.FromEventPattern
等创建一个。
One quibble: Select
is ideally run with no side-effects and DownloadFileViaFtp
is very much a side-effect. 一个狡辩:
Select
是理想的运行没有副作用, DownloadFileViaFtp
是一个非常副作用。 Side-effects are best in a Subscribe
call. 在
Subscribe
电话中,副作用最好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.