感谢您在以下问题上的帮助: 我班上有一个属性,可以说
string Foo {get;set;}
该类中有一个刷新功能。有一个长期运行的方法可以更新
Foo = await Task.Run()... etc.
当每秒调用1000 Refresh时,如何避免Task-s的堆积?防弹跳?节流吗?怎么做? Rx在项目中可用,我正在使用dotnet core 2.2。
类构造器
res = Observable.FromAsync(() => Task.Run(async () =>
{
await Task.Delay(5000);
return "Example";
}
)).Throttle(TimeSpan.FromSeconds(10));
课程
private IObservable<string> res;
public string Foo
{
get => _foo;
set
{
this.RaiseAndSetIfChanged(ref _foo, value);
}
}
public void RefreshFoo()
{
res.Subscribe(x => Foo = x);
}
答案 0 :(得分:0)
最后我得到了这个解决方案。
工作原理如下:
代码示例:
private long _refreshCalls;
public async Task RefreshHistoriesAsync()
{
try
{
if (Interlocked.Read(ref _refreshCalls) == 2) //it is running and scheduled to rerun after finished
{
return;
}
if (Interlocked.Read(ref _refreshCalls) == 1) //it is running but now we will rerun if finished
{
Interlocked.Increment(ref _refreshCoinCalls);
return;
}
if (Interlocked.Read(ref _refreshCalls) == 0) //it is not running so we start the work
{
Interlocked.Increment(ref _refreshCalls);
}
const int simultaneousThread = 2; //threads allowed to run simultaneously in threadpool
await Task.Run(() => Parallel.ForEach(myListOfItemsToWorkOn, new ParallelOptions { MaxDegreeOfParallelism = simultaneousThread }, item =>
{
LongRunningWork();
}));
if (Interlocked.Read(ref _refreshCoinCalls) == 2) //scheduled to rerun so we start the work again
{
Interlocked.Exchange(ref _refreshCoinCalls, 0);
RefreshHistoriesAsync();
}
if (Interlocked.Read(ref _refreshCoinCalls) == 1) //done with the job
{
Interlocked.Exchange(ref _refreshCoinCalls, 0);
}
}
catch (Exception ex)
{
Interlocked.Exchange(ref _refreshCoinCalls, 0);
//Log error
}
}
答案 1 :(得分:0)
如果您可以使用其他软件包,我建议使用ReactiveUI,它是ReactiveCommand,它将立即解决您的所有问题:
var command = ReactiveCommand.CreateFromTask(async () =>
{ // define the work
Console.WriteLine("Executing at " + DateTime.Now);
await Task.Delay(1000);
return "test";
});
command.Subscribe(res => {
// do something with the result: assign to property
});
var d = Observable.Interval(TimeSpan.FromMilliseconds(500), RxApp.TaskpoolScheduler) // you can specify scheduler if you want
.Do(_ => Console.WriteLine("Invoking at " + DateTime.Now))
.Select(x => Unit.Default) // command argument type is Unit
.InvokeCommand(command); // this checks command.CanExecute which is false while it is executing
输出:
Invoking at 2019-01-22 13:34:04
Executing at 2019-01-22 13:34:04
Invoking at 2019-01-22 13:34:05
Invoking at 2019-01-22 13:34:05
Executing at 2019-01-22 13:34:05
我知道该软件包主要用于UI开发,但没有什么好用的技巧,例如ReactiveCommand,您可以在任何地方使用它。
请注意,await command.Execute()
在默认情况下不会检查是否可以执行命令。
我认为这比您的解决方案更具可读性。