What Am I Missing About Reactive Extension Timers? - c#

I have this:
watchers
.ToObservable() // needs to be observable
.SelectMany(watcher => // working on each watcher
Observable
// create a timer for the watcher
.Timer(watcher.StartTime, TimeSpan.FromHours(watcher.Interval))
.SelectMany(Observable.FromAsync(
async () => new { watcher, result = await CheckFolder(watcher.Path) })))
.Subscribe(x => Console.WriteLine(string.Format("Watcher: {0}\tResult: {1}\tTime: {2}", x.watcher.Name, x.result, DateTimeOffset.Now))); // tell everyone what happened.
Which is a nice little bit of code from this post that got me started down this road. The goal is to ping a web service (via the CheckFolder() method) every time the Timers publish, based on a given start time and interval.
The trouble is, every time I run the program it outputs a single message for the first Watcher, and then the program exits without error. It gets the first answer, and it's finished.
How do get it to wait for the other publications from all the timers?
I'm almost positive I'm not asking this question the right way, but hopefully a little feedback will help me refine my question.
Thanks.

This is likely because Subscribe is a non-blocking call. I.e. if you have;
static void Main(string[] args)
{
Observable.Timer(DateTimeOffset.Now, TimeSpan.FromSeconds(0.5))
.Subscribe(x => Console.WriteLine("Got " + x));
}
You'll probably find it prints nothing (or maybe "Got 0", depending on how your PC is feeling)
If you stop Main from exiting, by waiting for a key to be pressed, like this:
static void Main(string[] args)
{
Observable.Timer(DateTimeOffset.Now, TimeSpan.FromSeconds(0.5))
.Subscribe(x => Console.WriteLine("Got " + x));
Console.ReadKey();
}
Then it should keep printing out values until you press a key.
The thing to remember is that having an activating subscription, isn't enough to keep your programming running. If you're writing an application with some UI, then you'll usually have a message loop - which will your program alive until you close the window. But that isn't the case for console apps, once you get to the end of main, that's the end of your program.
So you need to find a way to avoid your app exiting before you're reading. Waiting for a specific key to be pressed is a common way to do it, so that may work for you. e.g.
static void Main(string[] args)
{
Observable.Timer(DateTimeOffset.Now, TimeSpan.FromSeconds(0.5))
.Subscribe(x => Console.WriteLine("Got " + x));
while (Console.ReadKey().Key != ConsoleKey.Q)
{
}
}

Related

Why C# Rx Subscribe() function doesn't work with "async" keyword?

I've got this code snippet:
static void Main(string[] args)
{
Observable.Range(1, 5).Subscribe(async x => await DoTheThing(x));
Console.WriteLine("done");
}
static async Task DoTheThing(int x)
{
await Task.Delay(TimeSpan.FromSeconds(x));
Console.WriteLine(x);
}
I hope it will loop 5 times and after each loop there'll be a line printed as
1
2
3
4
5
But supprisingly, this will print "done" and terminate at once. Seems that async+await didn't wait the Task.Delay and quit.
Semantics doesn't seem to have problem, so where did I get wrong about Subscribe or async, how to fix it to fulfill my request of calling asynchrous tasks from Rx?
Thanks.
It's not blocking, because it's well - asynchronous.
Your code generates five tasks, all running parallel, all completing at various times.
But they do not block the Main function.
If you just add a Console.ReadKey() as your last line, you'll see that your code does run in the background. It prints.
static void Main(string[] args)
{
Observable.Range(1, 5).Subscribe(async x => await DoTheThing(x));
Console.WriteLine("done");
Console.ReadKey();
}
But suppose you want to wait until all of them were done. What then?
Of course, there's .Wait(), but that's blocking. Let's observe all of our tasks as observables.
We'll use C# 7's async Main while we're at it.
static async Task Main(string[] args)
{
await Observable.Range(1, 5)
.Select(x => DoTheThing(x).ToObservable())
.Merge();
Console.WriteLine("done");
}
This works exactly like you'd expect it to.

Notifying asynchronous subject from another observable using Rx .NET

I'm trying to notify listeners who subscribed to Subject _sub from another observable and after that log some message in Do handler. I'm calling OnNext and everything would work fine if _sub wasn't asynchronous. The problem here is that there is no OnNextAsync function which I would await in the first observable. What is the best way to do this?
class Program
{
private static Subject<int> _sub = new Subject<int>();
static void Main(string[] args)
{
_sub.SelectMany(async _ =>
{
Console.WriteLine("SUB START: " + _);
await Task.Delay(3000);
Console.WriteLine("SUB END: " + _);
return 1;
}).Subscribe();
Start();
}
public static void Start()
{
int count = 0;
Observable.Interval(TimeSpan.FromSeconds(5)).Select(x =>
{
Console.WriteLine("START INTERVAL");
_sub.OnNext(count++); //onNext is not awaitable
Console.WriteLine("END INTERVAL");
return 1;
})
.Do(_ => Console.WriteLine("ALL FINISHED"))
.Subscribe();
Console.WriteLine("READLINE");
Console.ReadLine();
}
}
Result:
READLINE
START INTERVAL
SUB START: 0
END INTERVAL
ALL FINISHED
SUB END: 0
Expected result:
READLINE
START INTERVAL
SUB START: 0
SUB END: 0
END INTERVAL
ALL FINISHED
An observable should not rely on the behavior of its observers.
I suggest you rethink the whole thing. What you're doing looks more interactive than reactive.
I'm going to echo Paulo for clarity:
Observables shouldn't care about Observers. While an Observable will wait on its synchronous Observers, it's best to think of this as an accident of implementation. An observable doesn't wait at all on an asynchronous Observer. Either way, the waiting shouldn't be relied upon.
You should really re-think how you're doing this. You're using a reactive library to write interactive code. Probably either the wrong choice of tool or a misuse of the tool.
Your code is littered with Rx code-smells. Think of reactive code as a flowchart. A flowchart of your code would look like spaghetti. It should look more like a binary tree.
This sounds like an XY problem: I would suggest re-phrasing your question with what you're trying to accomplish.

Start threads at the order that they were started, only when previous thread was finished

Sorry for the confusing title, but that's basically what i need, i could do something with global variables but that would only be viable for 2 threads that are requested one after the other.
here is a pseudo code that might explain it better.
/*Async function that gets requests from a server*/
if ()//recieved request from server
{
new Thread(() =>
{
//do stuff
//in the meantime a new thread has been requested from server
//and another one 10 seconds later.. etc.
//wait for this current thread to finish
//fire up the first thread that was requested while this ongoing thread
//after the second thread is finished fire up the third thread that was requested 10 seconds after this thread
//etc...
}).Start();
}
I don't know when each thread will be requested, as it is based on the server sending info to client, so i cant do Task.ContiuneWith as it's dynamic.
So Michael suggested me to look into Queues, and i came up with it
static Queue<Action> myQ = new Queue<Action>();
static void Main(string[] args)
{
new Thread(() =>
{
while (1 == 1)
{
if (myQ.FirstOrDefault() == null)
break;
myQ.FirstOrDefault().Invoke();
}
}).Start();
myQ.Enqueue(() =>
{
TestQ("First");
});
myQ.Enqueue(() =>
{
TestQ("Second");
});
Console.ReadLine();
}
private static void TestQ(string s)
{
Console.WriteLine(s);
Thread.Sleep(5000);
myQ.Dequeue();
}
I commented the code, i basically need to check if the act is first in queue or not.
EDIT: So i re-made it, and now it works, surely there is a better way to do this ? because i cant afford to use an infinite while loop.
You will have to use a global container for the threads. Maybe check Queues.
This class implements a queue as a circular array. Objects stored in a
Queue are inserted at one end and removed from the other.
Queues and stacks are useful when you need temporary storage for
information; that is, when you might want to discard an element after
retrieving its value. Use Queue if you need to access the information
in the same order that it is stored in the collection. Use Stack if
you need to access the information in reverse order. Use
ConcurrentQueue(Of T) or ConcurrentStack(Of T) if you need to access
the collection from multiple threads concurrently.
Three main operations can be performed on a Queue and its elements:
Enqueue adds an element to the end of the Queue.
Dequeue removes the oldest element from the start of the Queue.
Peek returns the oldest element that is at the start of the Queue but does not remove it from the Queue.
EDIT (From what you added)
Here is how I would change your example code to implement the infinite loop and keep it under your control.
static Queue<Action> myQ = new Queue<Action>();
static void Main(string[] args)
{
myQ.Enqueue(() =>
{
TestQ("First");
});
myQ.Enqueue(() =>
{
TestQ("Second");
});
Thread thread = new Thread(() =>
{
while(true) {
Thread.Sleep(5000)
if (myQ.Count > 0) {
myQ.Dequeue().Invoke()
}
}
}).Start();
// Do other stuff, eventually calling "thread.Stop()" the stop the infinite loop.
Console.ReadLine();
}
private static void TestQ(string s)
{
Console.WriteLine(s);
}
You could put the requests that you receive into a queue if there is a thread currently running. Then, to find out when threads return, they could fire an event. When this event fires, if there is something in the queue, start a new thread to process this new request.
The only thing with this is you have to be careful about race conditions, since you are communicating essentially between multiple threads.

Is there no way to Wait in C#?

There is a command that usually makes the program wait. Now I know how to make the Program wait while also freezing all input, but that's not what I'm trying to achieve. I'm making a simple Windows Console Application, just to start me up on things.
String name;
Console.WriteLine("What is your name?");
name = Console.ReadLine();
Console.WriteLine("Hello, {0}", name);
Now I'd like to have it wait while also allowing any input, so that way I could run something else, but also have it to where you can actually have it say Hello, (Insert Name Here)
And also, as mentioned before that I'm very new, please try to explain what you're answer involves, thanks!
Outside of ReadLine which you are already using that waits for user input, Thread.Sleep as in below is one basic method of stopping the application for X amount of time to wait for an execution to finish or a user to be ready. Thread.Sleep blocks execution though in more complex applications:
Thread.Sleep(2000);
Getting into an advanced way, you can use Asynchronous programming concepts and use Task.Delay. This doesn't block a thread like sleep and it means you can do this using a single thread using the async programming model. This sample code creates a new method, says it's async and defines it as a Task which is basically a unit of work, again more advanced concept wise but just to give you a high level idea/overview.
async Task TaskDelay()
{
await Task.Delay(2000);
}
private async void Test()
{
// Console.WriteLine etc. etc
await PutTaskDelay();
MessageBox.Show("Hello, I'm done waiting.");
}
I believe the question is:
How do wait in the main thread for user input, while working on some other task in the background?
class Program
{
static void Main(string[] args)
{
AsynchronousTask();
Console.WriteLine("What is your name?");
var name = Console.ReadLine();
Console.WriteLine("Hello, {0}", name);
Console.ReadLine();
}
private static async void AsynchronousTask()
{
Task.Run(() =>
{
while (true)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Async tas is running in the background.");
Console.ForegroundColor = ConsoleColor.White;
Thread.Sleep(1000); //this is just to slowdown background thread
}
});
}
}
While this example is very basic it shows how to get some code running in background. The topic you may wish to explore is called Asynchronous Programing

Task.Factory.StartNew() or Task.Run() correct usage?

I am new to multithreading and I’m hard time of making sense of all the ways to do it with tasks. I am trying to implement it in a big program but no one wants to look at all thousands of lines of processing code for no reason so i have write a simple test program that uses Sleep() instead of doing real work and made it real simple.
Question is as the bottom.
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
BlockingCollection<int> col = new BlockingCollection<int>();
for(int z = 0; z<=50; z++)
{
col.Add(z);
}
Console.WriteLine("Hi from main! ThreadID: {0}", Thread.CurrentThread.ManagedThreadId);
var parent = Task.Factory.StartNew(() =>
{
Console.WriteLine("Hi from PARENT! ThreadID: {0}", Thread.CurrentThread.ManagedThreadId);
foreach (int num in col.GetConsumingEnumerable())
{
Thread.Sleep(100);
Task.Factory.StartNew(() =>
{
Thread.Sleep(num*100);
if (num == 50)
{
col.CompleteAdding(); //kick out of the foreach loop
Thread.Sleep(25000);
}
Console.WriteLine("Hi from a Child! ThreadID: {0}", Thread.CurrentThread.ManagedThreadId);
}, TaskCreationOptions.AttachedToParent);
}
Console.WriteLine("Parent done making children. ThreadID: {0}", Thread.CurrentThread.ManagedThreadId);
}, TaskCreationOptions.LongRunning);
var final = parent.ContinueWith((antecedent) =>
{
Console.WriteLine("DONE!");
},TaskContinuationOptions.OnlyOnRanToCompletion
);
Console.WriteLine("Calling Wait on final. ThreadID: {0}", Thread.CurrentThread.ManagedThreadId);
final.Wait();
Console.ReadLine();
}
}
}
The code adds 51 elements to a blocking collection and then starts up a task called Parent. Parent consumes items from the blocking collection until it is marked with CompleteAdding() is called on it.
The parent task is long running as i don't want it pulling threads from the threadpool. It should then spawn attached child tasks that will sleep for some time and if the element is '50' it calls CompleteAdding().
Then there is a continuation called final that only runs if the parent ran to completion. And the parent can only be complete if the blocking collection is done being added too and all the child task are also complete.
I then call final.Wait() from main (in my real program the the final.Wait() will likely be in the OnFormClosing() method.)
The whole point of doing all this is to be able to ensure before the program closes all currently running work is finished and all queued work is also finished.
This is where the question is. I have seen in many places that I should use Task.Run() instead of Task.Factory.StartNew() so I tried changing them out and I start getting errors saying Error CS1643 Not all code paths return a value in lambda expression of type 'Func<Task>' why do i need a return value if I don't want a return. Also Is this proper use of Task.Factory.StartNew() or am I doing something risky/dangerous?
note Not sure if it matters but in the program I am going to use this setup in the sleeps with be stuff like matching data and sending it out to an oracle db. Also we can't go higher than .NET 4.6
Let's simplify the Task.Run version of your code:
Task.Run(() => { }, TaskCreationOptions.LongRunning);
This code is wrong: there is no overload of Task.Run() accepting TaskCreationOptions. But the error message reported by the C# compiler ("Not all code paths return a value in lambda expression of type 'Func<Task>'") is also wrong. I think this is a bug in the C# compiler, so I reported it.
Microsoft's documentation describes Task.Runas the 'simpler way' to run a task asynchronously. It and Task.Factory.StartNew both return a Task and the syntax is the same. I'd be interested in seeing the code that's giving you a compile error. But if your code is working with Task.Factory.StartNew I don't see a compelling reason to change it.
Task.Run(() =>
{
Console.Write("Doing");
Console.Write("Something");
});
Task.Factory.StartNew(() =>
{
Console.Write("Doing");
Console.Write("Something");
});

Categories