Observable return collection of collection - c#

I'm just starting to learn Observable and all it variations and run into some strange problem. Here it is:
I have a WCF service declaration (after 'Add Service reference' process):
public IAsyncResult ReceiveAllUsersAsync(AsyncCallback Callback, object State)
{
// Do some work
}
and here the closing one:
public IObservable<User> EndReceiveAllUsers(IAsyncResult AsyncResultHandler)
{
// Do some work (actuall y it's a: return AsyncResultHandler.EndInvoke();
// return IObservable<User>
}
as you can see the EndReceiveAllUsers return collection of User's
next I run an RX like so:
// This will not owrk
Func<IObservable<User>> callWcfService = Observable.FromAsyncPattern<IObservable<User>>(BeginReceiveAll, EndReceiveAll);
// Actuall Func<> signature is:
Func<IObservable< IObservable<User> >> callWcfService = Observable.FromAsyncPattern<IObservable<User>>(BeginReceiveAll, EndReceiveAll);
but the problem is that whatever returned from Observable.FromAsyncPattern is IObservable<> of IObservable<User>. Actually it return IObservable< IObservable<User> >. How I could return just one result of IObservable<User> and not the collection of result

It really depends on the behavior you want, but to answer your question directly, you can simply concatenate each sequence of users after the completion of the last one:
IObservable<IObservable<User>> tooMuch = callWcfService();
IObservable<User> justRight = tooMuch.Concat();

Edit:
Observable abstracts the multiple calls to ReceiveAllUsersAsync/EndReceiveAllUsers for you, so each time you get a whole IEnumerable<User>, it's produced as a whole by Observable. So if you want to produce the Users one by one, you need to switch to functions that produce users one at a time. ReceiveAllUsersAsync is not the function you need, as it waits until all the users are obtained, and gives them all back in a pack.
The one thing you can do is to convert the obtained IEnumerable<User> to IObservable<User>, but this will again behave in such a way: (1) get all the users under the hood, (2) produce all of them without pause -- which is not what you expect from a decent IObservable<>.
Old answer, for reference:
Looking at http://msdn.microsoft.com/en-us/library/hh212031%28v=vs.103%29.aspx:
public static Func<IObservable<TResult>> FromAsyncPattern<TResult>(
Func<AsyncCallback, Object, IAsyncResult> begin,
Func<IAsyncResult, TResult> end
)
So you perhaps just need Observable.FromAsyncPattern<User>, as User is your TResult.

Related

Reactive Extensions unfold / scan approach for nested hierarchy

I'm currently building a wizard system for an application, and we're using ReactiveUI and as a result Rx.
Each step in the wizard implements IWizardStep<T> where T is just the data type that the wizard ultimately produces.
Each step has the capability of surfacing which step should be available for the user to move to next, so as to enable branching based on data entry.
The step can be thought of having a similar structure to:
public interface IWizardStep<T>
{
IObservable<IStepChoice<T>> NextStepChoice {get;}
}
With IStepChoice<T> simply being:
public interface IStepChoice<T>
{
IWizardStep<T> Step {get;}
string Reason {get;}
}
In order to calculate the current path from the start to the end, for display to the user, I need to be able to go from the starting step, and walk along the NextStepChoice chain recursively until it hits a null (it's valid behaviour for the NextStepChoice observable to emit a null to indicate the end of the wizard).
I've taken a look at Observable.Scan but can't for the life of me work out how to get this working properly recursively.
I've also taken a look at Observable.Generate which looks promising, as this is a classic unfold-esque problem; the only issue is that Generate takes a function to determine when to break the loop, but I need to evaluate the inner observable to work this out.
Observable.Generate(
new WizardStepChoice<T>(start, null),
choice => choice != null,
choice => choice.ChosenStep.NextStepChoice,
choice => choice);
This would be ideal, and produce the output I'm after, but the NextStepChoice selector there obviously doesn't compile because it's an IObservable<IWizardStepChoice<T>> rather than an IWizardStepChoice<T>.
I've looked at using Aggregate and Scan but as these are more fold-driven operations, and I've only got the starting element, it's an unfold I'm looking for ala Generate, but I need it to be able to evaluate the nested observable.
Would Observable.Create perhaps be something I could utilise? I've tried it and come up with:
Path = CurrentStep.Select(_ => Observable.Create<IWizardStep<T>>(async observer =>
{
IWizardStepChoice<T> next = new WizardStepChoice<T>(start, null);
observer.OnNext(next.ChosenStep);
while (next != null)
{
next = await next.ChosenStep.NextStepChoice;
observer.OnNext(next.ChosenStep);
}
observer.OnCompleted();
return Disposable.Empty;
}).Aggregate(new List<IWizardStep<T>>(),
(l, s) =>
{
l.Add(s);
return l;
})).Switch().Publish().RefCount();
Which has all the right signature I want IWizardStep<T>->IReadOnlyList<IWizardStep<T>>, so at first glance it looks right, but it doesn't work; it fires, and I can step through, but it hangs once it hits the await and doesn't come back.
I've got a feeling I'm close, and this is a scheduling issue, so my question really is this:
What is the best approach to solve this, am I close?
If this is right, why is there an issue with the await, and how might I solve it?
Update
After a little bit of tinkering I noticed that the await was likely hanging as that observable hadn't yet (and wasn't going to) emit a value (duh), which I've now resolved by initialising each step with a value at the beginning of the wizard.
I've even sanity-checked this by adding a property to IWizardStep<T> - IWizardStepChoice<T> LatestStepChoice {get;} which is just hooked up with:
NextStepChoice.Subscribe(c => _latestStepChoice = c);
This is done on the step class itself, and I can confirm it's working just fine.
Yet still the await hangs, so I tried:
Making it Replay(1) so the await calling .Subscribe() would get the value - this didn't work
Making it Repeat() so even if something is subscribed it'll see the new value - this just made the whole thing hang.
Clearly I'm missing something here, I want it so that when the await queries the observable, it will be given the latest value seen, which is what I thought Replay(1) would achieve; I've also tried PublishLast() but then future updates don't get honoured because of the AsyncSubject<T> behaviour.
For now I've switched to using the self-subscribed property, but it's not ideal, I'd rather not have to break out of querying the observables if I can help it, it feels "hacky".
A recursive walk can transform the tree of observables into a single observable:
static IObservable<IWizardStep<T>> Walk<T>(IWizardStep<T> step)
{
if (step?.NextStepChoice == null)
return Observable.Return(step);
return step.NextStepChoice.SelectMany(choice => Walk(choice.Step)).StartWith(step);
}
Usage:
var steps = await Walk(step).ToArray();

How would I write this code with Reactive Programming?

I just started messing around with reactive programming, and I know just enough to write code but not enough to figure out what's happening when I don't get what I expect. I don't really have a mentor available other than blog posts. I haven't found a very good solution to a situation I'm having, and I'm curious about the right approach.
The problem:
I need to get a Foo, which is partially composed of an array of Bar objects. I fetch the Bar objects from web services. So I represented each web service call as an IObservable from which I expect 0 or 1 elements before completion. I want to make an IObservable that will:
Subscribe to each of the IObservable instances.
Wait for up to a 2 second Timeout.
When either both sequences complete or the timeout happens:
Create an array with any of the Bar objects that were generated (there may be 0.)
Produce the Foo object using that Bar[].
I sort of accomplished this with this bit of code:
public Foo CreateFoo() {
var producer1 = webService.BarGenerator()
.Timeout(TimeSpan.FromSeconds(2), Observable.Empty<Bar>());
var producer2 = // similar to above
var pipe = producer1.Concat(producer2);
Bar[] result = pipe.ToEnumerable().ToArray();
...
}
That doesn't seem right, for a lot of reasons. The most obvious is Concat() will start the sequences serially rather than in parallel, so that's a 4-second timeout. I don't really care that it blocks, it's actually convenient for the architecture I'm working with that it does. I'm fine with this method becoming a generator of IObservable, but there's a few extra caveats here that seem to make that challenging when I try:
I need the final array to put producer1 and producer2's result in that order, if they both produce a result.
I'd like to use a TestScheduler to verify the timeout but haven't succeeded at that yet, I apparently don't understand schedulers at all.
This is, ultimately, a pull model, whatever gets the Foo needs it at a distinct point and there's no value to receiving it 'on the fly'. Maybe this tilts the answer to "Don't use Rx". To be honest, I got stuck enough I switched to a Task-based API. But I want to see how one might approach this with Rx, because I want to learn.
var pipe = producer1
.Merge(producer2)
.Buffer(Observable.Timer(TimeSpan.FromSeconds(2), testScheduler))
.Take(1);
var subscription = pipe
.Select(list => new Foo(list.ToArray())
.Subscribe(foo => {} /* Do whatever you want with your foo here.*/);
Buffer takes all elements emitted during a window (in our case in two seconds), and outputs a list.
If you want to stick with your pull model, instead of a subscription you could do:
var list = await pipe;
var foo = new Foo(list.ToArray());
//....

Compare parameters of multiple callbacks

I am programming a game using the Unity Engine and I am currently running into the following problem:
I have a method that asynchronously returns his result using the parameters of a callback function. Pretty straightforward, it looks like this:
public void CalculateSomething( - PARAMETERS - , Action<float> callback)
I have to call this method in a loop for different parameters.
foreach(float f in manyFloats){
CalculateSomething(f, myCallback);
}
void myCallback(float f){
...compare this result value to the other values?...
}
Now I would like to compare the resulting floats, that come with the different callbacks. Let's just say I want to find the highest value among those floats. How do I do that?
I had the idea to store the results in an array field and just compare after it is fully filled, but I don't know how to check if all callbacks are done already.
Ideally I'd like to avoid polluting my class with a field like this, but it would be alright if there is no other way.
The CalculateSomethingfunction is part of a library, so I can't change it. Everything else is variable.
Here is the deal.
You got it right about creating the array and storing the values and compare them when all callbacks are done. Hence the problem is that you don't know when all the callbacks are returned. But you know how many callbacks are there based on count of your origin manyFloats variable. All you need to do is keep a counter and add it up every time a callback is returned. And check if it equals the count of manyFloats then you can do the comparison:
int count = 0;
void myCallback(float f)
{
... usual stuff
... then
if(count == manyFloats.Count)
{
// do the comparison
}
else
{
count ++;
}
}
Rather than using a callback based model you should use a Task based model. Have CalculateSomething return a Task<float> instead of having a callback. This allows you to use the TPL to compose these Task objects by writing code like:
var highestResult = (await Task.WhenAll(manyFloats.Select(CalculateSomething))).Max();
If you can't edit the method itself, then create your own wrapper that transforms the method into a task based version.
So, if we have no control over CalculateSomething function, we still can store max value and make comparison in our callback. Something like this:
void callbackFunction( float numb){
if (numb > maxNumb) //maxNumb is global
maxNumb = numb;
}
then you can use your foreach loop to go through your array. Just keep in mind that you would need to declare your maxValue global variable and make it initially equal to minimum value.
Even if you are not doing Min/Max comparison, and it is something more complicated, you still can do it in callback function. No need for arrays, because even with arrays if you can do it with single pass through array - you can do it in a callback function.

IEnumerable -- how non-empty collection can be empty at the same time?

I cannot figure this out. The workflow of passing IEnumerable<T> (T is some my class, but it is not relevant here) basically looks like this:
var a = GetEntireCollection(); // so I get IEnumerable<T>
...
var b = a.Where(condition1);
...
var c = b.Where(condition2);
...
So I filter out more and more items from the collection, finally I call:
if (z.IsEmpty())
throw new Exception();
Foo(z);
and Foo is
public void Foo(IEnumerable<T> p)
{
pool = p.OrderByDescending(it => it.MyProperty).ToList();
if (pool.IsEmpty())
throw new Exception(pool.Count().ToString() + ", " + p.Count().ToString());
...
All I do, is order the collection.
Now, my program crashes with exception -- it says that p has Count = 1, and pool has Count = 0. What's more when I point out p and require the results (I run program using Visual Studio) it says, the collection yielded with no results (or somethig similar, not verbatim quote).
Questions:
how can non-empty collection become empty just by reordering?
how can collection Count can be > 0, when there are no items in it?
I am asking because I would like to know how to avoid this situation, but honestly, when I am looking at the code it seems 100% legit for me.
Technical background:
it is pure C# code, no asm inlines, or anything like this
no threads
no external libraries, except for Where (which comes from Linq) this is all my code
Edits
Edit 1
public static bool IsEmpty<T>(this IEnumerable<T> coll)
{
var iter = coll.GetEnumerator();
return !iter.MoveNext();
}
Edit 2
Just before I call Foo(z) I check if the z is empty, so the code looks like this:
if (z.IsEmpty())
throw new Exception();
Foo(z);
SOLVED
As Jon suggested (C# sharpshooting I would say) one of the conditions was time dependent. So when the collection evaluation was forced the condition changed and I get in fact another collection.
One possibility is that evaluating the conditions twice is effectively changing the results.
Each time you iterate through p, it will re-evaluate the data, including the Where clauses. So you're doing that once to populate pool, and then again to print out p.Count().
Without any more information about what GetEntireCollection does or what the Where conditions are, it's hard to say what's going on... but that's one possible explanation. If you can post a short but complete program demonstrating the problem, that would help a lot.
It's empty because of Deferred Execution, most query operators execute not when
constructed, but when enumerated (in other words, when MoveNext is called on its
enumerator).
So if you change it to :
var c = b.Where(condition2).ToList();
And then call Foo(c) it will work.
I think the code you show will call GetEntireCollection multiple times.
So maybe this method is returning different results on successive invocations.

Cancellable Sort in .NET?

I'm using ListView in VirtualMode to show extremely big number of rows, millions of rows.
The data of the rows stored in a Generic List.
Now i want implement a sort feature, that will sort the List by some Comparer.
The problem is that for now, an average single sort takes around 30 seconds, and during this time the user cannot do anything with the ListView and have to wait until it ends.
Not every user will accept to wait that much time, most of users would cancel the sort, if they could, and i want to allow that cancel feature. Unfortunately, the built-in List.Sort cannot be cancelled nor Array.Sort.
For now the sort occurring on separate thread, so I could use Thread.Abort, but it probebly will result in corrupted List, unacceptable for me.
Is there something i can do except reimplement the whole Sort algorithm by myself?
thanks.
Copy the list, sort the copy in a thread then replace the original list (if the sort completes without getting interrupted).
But I'd go with Martinho's suggestion if possible - having the millions of rows in the application to begin with feels wrong to me. Databases can do a far better job of filtering and sorting data before it gets to you.
I had a similar problem. Beating the framework Array.Sort is not easy, and using Thread.Abort is not recommended at all.
I decided sort operation would not be cancel-able, however I thought about this solution ( did not test it)
Implements your own comparer able to access your IAsyncResult object having a CancelRequested bool field. Before any comparison, check the bool, true throws an exception cought in your your bground thread. No thread abort e.g. any lock can be released correctly. Your initial items are safe. But you still need to build an array, either of ref or of keys indexing your original items, because throwing while comparing may leave the array corrrupted. I guess it is not the case but there's no guaranty for this.
Hope this helps
There are several ways you could do this. I might write a class that uses the standard BeginXXX/EndXXX asynchronous pattern with a special CancelXXX method. I have left out a lot of code, but I think there is enough here to make the point. Unfortunately with this method you would have to code your own sorting algorithm.
public class Sorter
{
public IAsyncResult BeginSort(IList<T> values, AsyncCallback complete)
{
MyAsyncResult asyncResult = new MyAsyncResult();
Thread t = new Thread(() =>
{
// Implement your sorting algorithm here.
// Periodically check asyncResult.Cancel at safe points.
asyncResult.Complete();
if (complete != null)
{
complete(asyncResult);
}
});
t.Start();
return asyncResult;
}
public void EndSort(IAsyncResult asyncResult)
{
MyAsyncResult target = asyncResult as MyAsyncResult;
if (target == null)
{
throw new ArgumentException();
}
// Add code here to extract any additional information from the IAsyncResult that
// you might want to return to the client. Perhaps this method will be empty.
}
public void CancelSort(IAsyncResult asyncResult)
{
MyAsyncResult target = asyncResult as MyAsyncResult;
if (target == null)
{
throw new ArgumentException();
}
target.Cancel = true;
}
private class MyAsyncResult : IAsyncResult
{
private volatile bool m_Cancel = false;
public bool Cancel
{
get { return m_Cancel; }
set { m_Cancel = value; }
}
public void Complete()
{
// Add code here to mark this IAsyncResult as complete.
}
}
}
depending completely upon the environment in question - one approach is to let the user cancel waiting for the sort (which is running on a separate thread) but you secretly continue sorting the list in the background and then tell them when its finished with a subtle notification.
If you need possibility to cancel sort then you have to create a separate thread. You can prevent corrupting of the original list by reating it's copy and sorting the copy. If user doesn't cancel sorting just exchange original list wist sorted one.

Categories