[英]Reactive Observable.Create for async producer without Task.Run
I want write function which will return items asynchronously: 我想要写函数,它将异步返回项目:
public static async Task<IEnumerable<T>> GetItems()
{
while (await ShouldLoopAsync())
{
yield return await GetItemAsync();
}
}
Of course it will not work. 当然不会。 In 1 they propose next solution:
他们在1中提出了下一个解决方案:
return Observable.Create<T>(
observer => Task.Run(async () =>
{
while (await ShouldLoopAsync())
{
observer.OnNext(await getAsync());
}
observer.OnCompleted();
}
)
);
I don't like accepted solution from 1 because it uses Task.Run method inside Observable.Create. 我不喜欢1接受的解决方案,因为它在Observable.Create中使用Task.Run方法。 I want some solution with reactive extensions which will run on the current TaskScheduler without using other threads except existing one.
我想要一些具有反应性扩展的解决方案,该解决方案可以在当前TaskScheduler上运行,而不使用现有线程以外的其他线程。 I can write such solution in declarative way using .net events but I can't with Rx.
我可以使用.net事件以声明的方式编写此类解决方案,但不能使用Rx。
UPDATE 更新
I tried to remove Task.Run
and write next test: 我试图删除
Task.Run
并编写下一个测试:
[TestClass]
public class ReactiveWithTaskIEnumerable
{
[TestMethod]
public void ReactibeShouldProcessValuesWithoutnakoplenie()
{
Trace.WriteLine($"Start Thread {Thread.CurrentThread.ManagedThreadId}");
var i = GetIntsAsync()
.Subscribe(
onNext: p =>
{
Trace.WriteLine($"onNext Thread {Thread.CurrentThread.ManagedThreadId} {p}");
},
onCompleted: () =>
{
Trace.WriteLine($"onCompleted Thread {Thread.CurrentThread.ManagedThreadId}");
},
onError: p =>
{
Trace.WriteLine($"onError Thread {Thread.CurrentThread.ManagedThreadId} {p}");
throw p;
}
);
Trace.WriteLine($"Finish Thread {Thread.CurrentThread.ManagedThreadId}");
}
private IObservable<int> GetIntsAsync()
{
return Observable.Create<int>(
observer => async () =>
{
Trace.WriteLine($"Produce {Thread.CurrentThread.ManagedThreadId}");
try
{
foreach (var i in Enumerable.Range(1, 10))
{
await Task.Delay(1000);
observer.OnNext(1);
}
}
catch (Exception e)
{
observer.OnError(e);
}
observer.OnCompleted();
});
}
}
And the output is: 输出为:
Start Thread 3
Finish Thread 3
So internal task doesn't start at all. 因此内部任务根本不会启动。
After that I changed GetIntsAsync
to this: 之后,我将
GetIntsAsync
更改为此:
private IObservable<int> GetIntsAsync()
{
return Observable.Create<int>(
observer =>
{
async Task Lambda()
{
Trace.WriteLine($"Produce {Thread.CurrentThread.ManagedThreadId}");
try
{
foreach (var i in Enumerable.Range(1, 10))
{
await Task.Delay(1000);
observer.OnNext(1);
}
}
catch (Exception e)
{
observer.OnError(e);
}
observer.OnCompleted();
}
return Lambda();
});
}
And this gives next output: 这给出了下一个输出:
Debug Trace:
Start Thread 3
Produce 3
Finish Thread 3
It is close to output with Task.Run
: 它与
Task.Run
输出Task.Run
:
Debug Trace: Start Thread 3 Produce 9 Finish Thread 3 调试跟踪:启动线程3产生9完成线程3
Now I need to wait until observable comes completion 现在我需要等到可观察到的完成
Have a go at NuGetting "System.Interactive" and then try this: 去NuGetting“ System.Interactive”,然后尝试以下操作:
public static IEnumerable<int> GetItems()
{
return EnumerableEx.Create<int>(async y =>
{
while (await ShouldLoopAsync())
{
await y.Return(GetItemAsync());
}
await y.Break();
});
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.