【发布时间】:2020-03-25 14:24:19
【问题描述】:
我有一个在浏览器中打开聊天机器人的按钮。问题是我没有直接知道聊天机器人的地址。我必须向第二台服务器询问该地址,所以我的按钮不会立即对点击做出反应。
如果按钮被快速单击两次,我希望它不要打开两个浏览器选项卡。 我需要一些看起来有点像 Throttle 的东西,但不是检查经过的时间,而是检查它放开的上一个事件是否已经终止。
我想我可以在反应式管道中使用布尔检查和过滤器来做到这一点,但我不想处理该布尔值上的线程安全性,因为我在第二个线程上启动进程。
例如,我有一个方法很长,比如调用 api 来获取地址:
private async Task<string> LongTask()
{
await Task.Delay(1000);
return "a return value";
}
我想一次处理一次,放弃在第一个事件完成处理之前发生的任何其他点击,有点像:
var longTaskObservable =
Observable.FromAsync(LongTask) // Create observable from async method that returns one value
.SubscribeOn(NewThreadScheduler.Default); // Run it on a background thread
bool inProgress = false;
Observable.FromEventPattern(btn, "Click") // On a click event
.Where(_ => !inProgress)
.Do(_ => inProgress = true)
.SelectMany(longTaskObservable) // Start the long task observable and use its unwrapped values instead of the event args
.Where(s => !string.IsNullOrEmpty(s)) // Exclude any results that are marked as invalid
.ObserveOnDispatcher() // Set the thread of the subscribe method after to the ui thread
.Subscribe(result => {
LogWithThread("Got result '" + result + "' on thread {0}");
inProgress = false;
}); // Get the result
但这不是很干净或清晰或模块化,很容易破坏。 看起来应该很简单。我一定是在这里遗漏了一些东西。
任何帮助将不胜感激! 谢谢
【问题讨论】:
-
您不能在单击时禁用按钮并在进程结束时重新启用它吗?
-
这基本上就是我在帖子中概述的内容。如果存在,我正在寻找一种反应式原生解决方案。或者至少更优雅的东西
标签: c# .net async-await reactive-programming system.reactive