.NET Stateless a parallel workflow / long parallel background process - c#

I have a stateMachine where I need to download a huge amount of data in the background at State.LoadingOrderInfos. While my application is downloading the stuff (in the background), the operator should work on and go through the next states.
At State.InsertPcbs I need the downloaded data.
In short words. I want to call LoadECMDataAsync when entering State.LoadingOrderInfos and it should not disturb the normal workflow.
_machine.Configure(State.LoadingOrderInfos)
.Ignore(Trigger.WtPresent)
.Ignore(Trigger.WtNotPresent)
.SubstateOf(State.CanLogOut)
.Permit(Trigger.OrderLoadingFailed, State.OrderNotSelected)
.Permit(Trigger.OrderLoadingComplete, State.OrderCheckSetup)
.OnEntry(() =>
{
IsLoading = true;
Wt = null;
})
// Is this the way how to do it?
.OnEntry(() =>
{
LoadECMDataAsync();
})
.OnActivate(async () =>
{
if (await _LoadOrderInfos().ConfigureAwait(true))
{
_machine.Fire(Trigger.OrderLoadingComplete);
}
else
{
_machine.Fire(Trigger.OrderLoadingFailed);
}
})
.OnExit(() => IsLoading = false);

I think I would create a service class that fetches the data you need, maybe you could use Task.Run int this class to start the process.
When it's done, it could set a flag that is checkable. Or you could make it so that it calls a callback.
Then use PermitIf to check if a flag has been set.
Your problem is ortogonal, so I think it makes sense to split up the responsibilities.
BTW, you are using OnActivate. This should only be used if you need to "Activate" the state machine, like if you reload it from storage. At the moment it works like OnEntry (so use that), but I'd like to change it...

Related

c# make my a specific line to timeout after x seconds c#

I have a line in C# which does not work very reliable and does not time out at all and runs for infinity.
to be more precise i am trying to check the connection to a proxy WebClient.DownloadString
I want it to timeout after 5 seconds without making the full method asynchronous
so the code should be like this:
bool success = false
do_this_for_maximum_5_seconds_or_until_we_reach_the_end
{
WebClient.DownloadString("testurl");
success = true;
}
it will try to download testurl and after it did download it it will set success to true. If DownloadString takes more than 5 seconds, the call is canceled, we do not reach the the line where we set success to true, so it remains false and i know that it field.
The thread will remain frozen while we try to DownloadString, so the action is not taking parallel. The ONLY difference to a normal line would be that we set a timeout after 5 seconds
Please do not suggest alternatives such as using HttpClient, because i need a similar codes also for other places, so i simply want a code which will run in a synchronous application (i have not learned anything about asynchronus programing therefore i would like to avoid it completely)
my approach was like suggested by Andrew Arnott in this thread
Asynchronously wait for Task<T> to complete with timeout
however my issue is, I am not exactly sure what type of variable "SomeOperationAsync()" is in his example (i mean it seems like a task, but how can i put actions into the task?), and the bigger issue is that VS wants to switch the complete Method to asynchronos, but i want to run everything synchronous but just with a timeout for a specific line of code.
In case the question has been answered somewhere kindly provide a link
Thank you for any help!!
You should use Microsoft's Reactive Framework (aka Rx) - NuGet System.Reactive and add using System.Reactive.Linq; - then you can do this:
var downloadString =
Observable
.Using(() => new WebClient(), wc => Observable.Start(() => wc.DownloadString("testurl")))
.Select(x => new { success = true, result = x });
var timeout =
Observable
.Timer(TimeSpan.FromSeconds(5.0))
.Select(x => new { success = false, result = (string)null });
var operation = Observable.Amb(downloadString, timeout);
var output = await operation;
if (output.success)
{
Console.WriteLine(output.result);
}
The first observable downloads your string. The second sets up a timeout. The third, uses the Amb operator to get the result from which ever of the two input observables completes first.
Then we can await the third observable to get its value. And then it's a simple task to check what result you got.

Concurrent calls to external services

I am currently working on a project to build an integration between an existing ASP.Net MVC website and a file hosting service my company is using. The typical use case is:
A user requests one or more files
The controller makes one call per file to the file host API
The file host returns the file data to the controller
The controller returns a file result
The hosting service can handle concurrent calls, and I've found that executing each API call within a task (see example below) leads to fairly drastic improvements.
private void RetrieveDocuments(DocumentIdentifier[] identifiers, List<FileHostResult> results)
{
var tasks = identifiers.Select(x => RetrieveDocument(results, x)).ToArray();
Task.WaitAll(tasks);
}
private Task RetrieveDocument(List<FileHostResult> results, DocumentIdentifier x)
{
return Task.Run(() =>
{
var result = GetFileHostResultFromFileHost(x.ExternalIdentifier);
lock (results)
{
results.Add(result);
}
});
}
My question is whether or not there is a better way of doing this, or if there are any potential pitfalls I might run into? (eg. locking server resources, etc).
EDIT 1: I didn't post the code for GetFileHostResultFromFileHost because I don't really have any access to change it. Its basically a method call implemented in a library I cant change.
EDIT 2: To clarify. My main concern is to avoid harming the current user experience on the site. To that end I want to make sure that running tasks concurrently out of an ASP.net mvc isn't going to lock up the site.
You should use Microsoft's Reactive Framework for this. It is ideally suited to this kind of processing.
Here's the code:
IObservable<FileHostResult> query =
from i in identifiers.ToObservable()
from r in Observable.Start(() => GetFileHostResultFromFileHost(i.ExternalIdentifier))
select r;
IList<FileHostResult> results = query.ToList().Wait();
That's it. It properly schedules the code on the optimum number of threads.
If you want awaitable code then you can do this:
IObservable<FileHostResult> query =
from i in identifiers.ToObservable()
from r in Observable.Start(() => GetFileHostResultFromFileHost(i.ExternalIdentifier))
select r;
IList<FileHostResult> results = await query.ToList();
It's really very simple and easy to code.
NuGet "System.Reactive" and then add using System.Reactive.Linq; to your code.
It is hard to give great advice without seeing the rest of the source code. But based on what I can see I'd suggest an approach like:
private void RetrieveDocuments(DocumentIdentifier[] identifiers, List<FileHostResult> results)
{
results.AddRange(identifiers.AsParallel().Select(x => RetrieveDocument(x)));
}
private FileHostResult RetrieveDocument(DocumentIdentifier x)
{
var result = GetFileHostResultFromFileHost(x.ExternalIdentifier);
return result;
}
The advantages of this approach:
No explicit use of Task.Run - let AsParallel take care of that for you.
No need for locking the results list - let AsParallel and Select take care of that for you
You may also wish to increase the maximum number of connections you have access to.
Being honest though, I think you should look at approaches that don't require new Tasks at all - likely by using Async http download calls which you can run in parallel without the overhead of a thread.

Cancelling and re-executing ReactiveCommand

I'm struggling with a ReactiveUI use case that I feel is so simple there must be "out-of-the-box" support for it. But I cannot find it.
The scenario is a basic search interface with these features:
A search string TextBox where the user enters the search text
A result TextBox where the result is presented
An indicator showing that a search is in progress
The search should work like this:
The search string TextBox is throttled, so that after 500ms of
inactivity, a search operation is initiated.
Each time a new search is initiated any ongoing search operation should be cancelled.
Basically I'm trying to extend the "Compelling example" to cancel the currently executing command before starting a new command.
Seems easy enough? Yeah, but I cannot get it right using ReactiveCommand. This is what I have:
var searchTrigger = this.WhenAnyValue(vm => vm.SearchString)
.Throttle(TimeSpan.FromMilliseconds(500))
.Publish().RefCount();
var searchCmd = ReactiveCommand.CreateFromObservable(
() => Observable
.StartAsync(ct => CancellableSearch(SearchString, ct))
.TakeUntil(searchTrigger));
searchCmd.ToPropertyEx(this, vm => vm.Result);
searchCmd.IsExecuting.ToPropertyEx(this, vm => vm.IsSearching);
searchTrigger.Subscribe(_ => searchCmd.Execute(Unit.Default).Subscribe());
The above code works in all aspects except searchCmd.IsExecuting. I kick off a new search regardless of the state of searchCmd.CanExecute. This makes IsExecuting unreliable since it assumes serial operation of the commands. And I cannot use InvokeCommand instead of Execute since then new searches would not be started while a search is in progress.
I currently have a working solution without ReactiveCommand. But I have a strong feeling this simple use case should be supported in a straightforward way using ReactiveCommand. What am i missing?
AFAICT Rx7 doesn't really handle this kind of overlapping execution. All the messages will eventually make it through but not in a way that will keep your IsExecuting consistently true. Rx6 used an In flight counter so overlapping executions were handled but Rx7 simplified it all way down. Most likely for performance and reliability (but I'm just guessing). Because Tasks aren't going to cancel right away that first command is going to complete after the second command starts which leads to IsExecuting toggling from true to false to true to false. But that middle transition from false to true to false happens instantly as the messages catch up. I know you said you had a non Reactive Command working but here's a version that I think works with Reactive Commands by waiting for the first command to finish or finish cancelling. One advantage to waiting until the Task actually cancels is that you are assured you don't have two hands in the cookie jar :-) Which might not matter in your case but can be nice in some cases.
//Fires an event right away so search is cancelled faster
var searchEntered = this.WhenAnyValue(vm => vm.SearchString)
.Where(x => !String.IsNullOrWhiteSpace(x))
.Publish()
.RefCount();
ReactiveCommand<string, string> searchCmd = ReactiveCommand.CreateFromObservable<string, string>(
(searchString) => Observable.StartAsync(ct => CancellableSearch(SearchString, ct))
.TakeUntil(searchEntered));
//if triggered wait for IsExecuting to transition back to false before firing command again
var searchTrigger =
searchEntered
.Throttle(TimeSpan.FromMilliseconds(500))
.Select(searchString => searchCmd.IsExecuting.Where(e => !e).Take(1).Select(_ => searchString))
.Publish()
.RefCount();
_IsSearching =
searchCmd.IsExecuting
.ToProperty(this, vm => vm.IsSearching);
searchTrigger
.Switch()
.InvokeCommand(searchCmd);

How do I test that a FileSystemWatcher raises the correct events?

I am using a System.IO.FileSystemWatcher in one of my services. I want to test that when a file being monitored is changed, I get a notification.
I was thinking about having a background thread change the file. In the test, I would join on that thread. Then I can assert that the correct events are called. I could subscribe a callback to capture if the event was called.
I have not done any testing involving threads so I am not sure if this is the best way to handle it or if there are some built in ways in Moq or MSpec that will help test.
Moq or MSpec don't have anything specifically built in that will help you do this, except for some interesting syntax or features that will help you organize your test. I think you're on the right path.
I'm curious how your service exposes file changed notifications. Does it expose them publicly for testing? Or is the FileSystemWatcher entirely hidden inside the service? If the service doesn't simply pass the event notification up and out, you should extract your file monitoring so that it can be easily tested.
You can do that with .NET events or callbacks or whatever. No matter how you go about it, I would write the test something like this...
[Subject("File monitoring")]
public class When_a_monitored_file_is_changed
{
Establish context = () =>
{
// depending on your service file monitor design, you would
// attach to your notification
_monitor.FileChanged += () => _changed.Set();
// or pass your callback in
_monitor = new ServiceMonitor(() => _changed.Set());
}
Because of = () => // modify the monitored file;
// Wait a reasonable amount of time for the notification to fire, but not too long that your test is a burden
It should_raise_the_file_changed_event = () => _changed.WaitOne(TimeSpan.FromMilliseconds(100)).ShouldBeTrue();
private static readonly ManualResetEvent _changed = new ManualResetEvent();
}

How can I view the number of concurrent HTTP requests being made by the server?

I am using a third party API to query data asynchronously. Here is an example of my code:
private void AsyncDataLoad() {
Task[] tasks = new Task[6] {
Task.Factory.StartNew(() => FetchSomeStuff1()),
Task.Factory.StartNew(() => FetchSomeStuff2()),
Task.Factory.StartNew(() => FetchSomeStuff3()),
Task.Factory.StartNew(() => FetchSomeStuff4()),
Task.Factory.StartNew(() => FetchSomeStuff5()),
Task.Factory.StartNew(() => FetchSomeStuff6())
};
Task.WaitAll(tasks);
}
How can I view how many requests I have open at one time? By default I think there is a limitation to the number of concurrent requests I can have open on one domain and I would like to change this. But, I want to be able to prove this is the fact before trying to make any changes.
My development box is on Windows 7 Enterprise if that helps for any tool suggestions. I tried using PerfMon, but, it didn't seem like any properties available for monitoring with that tool were picking up HTTP requests made by the server.
IME, fiddler is the best tool for viewing http call behavior. Its timeline lets you view concurrency nicely.
The setting for changing the limit is in connectionManagement
http://msdn.microsoft.com/en-us/library/fb6y0fyc.aspx
If you just need to manually watch it yourself (not inspect it programatically), then you could use TCPView from SysInternals.

Categories