MvvmCross Async command lock - asynchronous

I have alot of button in my application. They are placed next to each other. All of the methods are IMvxAsyncCommand type. I figured out some missmatches after tests done by users. I have found duplicate operations - two diffrent buttons are called in almost same time.
What did I do is created my own SafeAsyncCommand class and inheret from MvxAsyncCommand. My goal is to create delay between executes - I want to prevent double click in given delay in below case 0.5s.
There is my work:
public static class SafeCommandSettings
{
public static bool CanExecute { get; private set; }
public static TimeSpan Delay => TimeSpan.FromMilliseconds(500);
static SafeCommandSettings()
{
CanExecute = true;
}
public static async void Pause()
{
if (!CanExecute) return;
CanExecute = false;
await Task.Delay(Delay);
CanExecute = true;
}
}
public class SafeAsyncCommand : MvxAsyncCommand
{
public SafeAsyncCommand(Func<Task> execute, Func<bool> canExecute = null, bool allowConcurrentExecutions = false)
: base(execute, canExecute, allowConcurrentExecutions)
{
}
public SafeAsyncCommand(Func<CancellationToken, Task> execute, Func<bool> canExecute = null, bool allowConcurrentExecutions = false)
: base(execute, canExecute, allowConcurrentExecutions)
{
}
protected override async Task ExecuteAsyncImpl(object parameter)
{
if (!SafeCommandSettings.CanExecute) return;
SafeCommandSettings.Pause();
await base.ExecuteAsyncImpl(parameter);
}
}
public class SafeAsyncCommand<T> : MvxAsyncCommand<T>
{
public SafeAsyncCommand(Func<T, Task> execute, Func<T, bool> canExecute = null, bool allowConcurrentExecutions = false)
: base(execute, canExecute, allowConcurrentExecutions)
{
}
public SafeAsyncCommand(Func<T, CancellationToken, Task> execute, Func<T, bool> canExecute = null, bool allowConcurrentExecutions = false)
: base(execute, canExecute, allowConcurrentExecutions)
{
}
protected override async Task ExecuteAsyncImpl(object parameter)
{
if (!SafeCommandSettings.CanExecute) return;
SafeCommandSettings.Pause();
await base.ExecuteAsyncImpl(parameter);
}
}
I thought this is working but I saw users were able to do it again. Do I miss some knowledge about async methods or static thread safe?
Thanks in advance

In order to do so you can take advantage of MvxNotifyTask that is a wrapper of the Task that watches for different task states and you'll run on your command and do something like this (notice that you don't need the command to be MvxAsyncCommand):
public MvxNotifyTask MyNotifyTaskWrapper { get; private set; }
public MvxCommand MyCommand { get; private set; }
private void InitializeCommands()
{
// this command is executed only if the task has not started (its wrapper is null) or the task is not in progress (its wrapper is not IsNotCompleted)
this.MyCommand = new MvxCommand(() => this.MyNotifyTaskWrapper = MvxNotifyTask.Create(() => this.MyLogicAsync()),
() => this.MyNotifyTaskWrapper == null || !this.MyNotifyTaskWrapper.IsNotCompleted);
}
private async Task MyLogicAsync()
{
// my async logic
}
So as soon the async process is started the command can't be executed again preventing duplicate operations, and you can start it again when that task completes.
If you have to disable multiple commands execution when running some task just add the same CanExecute condition on the different commands or mix conditions of different MvxNotifyTask
Also check that the MvxNotifyTask raises property-changed notifications that you can subscribe to or bind to in your view displaying a "loading" or something like that when performing the operation.
Note: if you are using Mvx < 5.5 you won't have MvxNotifyTask but you can use NotifyTaskCompletion done by Stephen Cleary that is almost the same as MvxNotifyTask and it is from where MvxNotifyTask was based on.
HIH

Instead of delaying things, consider using AsyncLock by Stephen Cleary or lookup Interlocked.CompareExchange.
As far as I can tell from here, you shouldn't use a static CanExecute in your case, as it locks all commands using your "safe" command at once.
And there is the possibility of race conditions, since you aren't changing the value of CanExecute locked.

Related

Lazy CosmosDB Initialization takes longer when more tasks are waiting for it

Context
We have a service that is dependent on CosmosDB. We created a class, having a lazy container, that will be initialized on startup. In the startup class we do :
CreateDatabaseIfNotExist
CreateContainerIfNotExistsAsync
Problem
The first request to CosmosDB starts the initialization.
When we have multiple threads starting up before the initialization, waiting for this lazy intialization to finish, the intialization takes longer the more threads are waiting for it.
Expected
When multiple threads starting up, the threads that need to have this initialized container, should not impact the initialization duration, since this is in a locked context (lazy)
In the code example below, when changing the amount of threads to 5, the initialization is in a couple of seconds. the higher the count of threads, the higher the duration of the initialization.
code example:
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos;
namespace LazyCosmos.Anon
{
class Program
{
static void Main(string[] args)
{
new Do().Run().GetAwaiter().GetResult();
}
public class Do
{
private Lazy<Container> lazyContainer;
private Container Container => lazyContainer.Value;
public Do()
{
lazyContainer = new Lazy<Container>(() => InitializeContainer().GetAwaiter().GetResult());
}
public async Task Run()
{
try
{
var tasks = new Task[100];
for (int i = 0; i < 100; i++)
{
tasks[i] = Task.Run(() =>
ReadItemAsync<Item>("XXX", "XXX"));
}
await Task.WhenAll(tasks);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
public async Task<T> ReadItemAsync<T>(string id, string partitionKey)
{
var itemResponse = await Container.ReadItemAsync<T>(id, new PartitionKey(partitionKey));
return itemResponse.Resource;
}
private async Task<Container> InitializeContainer()
{
var s = Stopwatch.StartNew();
Console.WriteLine($"Started {s.ElapsedMilliseconds}s");
var configuration = new CosmosDbServiceConfiguration("XXX", null, collectionId: "XXX",
"XXX", 400);
var _cosmosClient = new ColdStorageCosmosClient(new ActorColdStorageConfiguration("XXX", "XXX", "https://XXX.XX", "XXX"));
var database = await _cosmosClient
.CreateDatabaseIfNotExistsAsync(configuration.DatabaseId, configuration.DatabaseThroughput);
Console.WriteLine($"CreateDatabaseIfNotExistsAsync took {s.ElapsedMilliseconds}s");
var containerProperties = new ContainerProperties
{
Id = configuration.ContainerId,
PartitionKeyPath = $"/{configuration.PartitionKey}",
DefaultTimeToLive = configuration.DefaultTimeToLive
};
var db = (Database)database;
var containerIfNotExistsAsync = await db.CreateContainerIfNotExistsAsync(containerProperties, configuration.ContainerThroughput);
s.Stop();
Console.WriteLine($"CreateContainerIfNotExistsAsync took {s.ElapsedMilliseconds}s");
return containerIfNotExistsAsync;
}
}
}
public class CosmosDbServiceConfiguration
{
public CosmosDbServiceConfiguration(string databaseId, int? databaseThroughput, string collectionId, string partitionKey, int? containerThroughput = null)
{
DatabaseId = databaseId;
ContainerId = collectionId;
DatabaseThroughput = databaseThroughput;
ContainerThroughput = containerThroughput;
PartitionKey = partitionKey;
}
public string DatabaseId { get; }
public int? DatabaseThroughput { get; }
public string ContainerId { get; }
public int? ContainerThroughput { get; }
public string PartitionKey { get; }
public int? DefaultTimeToLive { get; set; }
}
public class ColdStorageCosmosClient : CosmosClient
{
public ColdStorageCosmosClient(ActorColdStorageConfiguration actorColdStorageConfiguration) : base(actorColdStorageConfiguration.EndpointUrl, actorColdStorageConfiguration.Key)
{
}
}
public class ActorColdStorageConfiguration
{
public ActorColdStorageConfiguration(string databaseName, string collectionName, string endpointUrl, string key)
{
DatabaseName = databaseName;
CollectionName = collectionName;
EndpointUrl = endpointUrl;
Key = key;
}
public string DatabaseName { get; }
public string CollectionName { get; }
public string EndpointUrl { get; }
public string Key { get; }
}
public class Item
{
public string id { get; set; }
}
}
You're experiencing thread pool exhaustion. There's a few different concepts that are conflicting to cause the exhaustion.
First, even though asynchronous code does not use a thread for the duration of the asynchronous operation, it often does need to very briefly borrow a thread pool thread in order to do housework when the asynchronous operation completes. As a result, most asynchronous code only runs efficiently if there is a free thread pool thread available, and if there are no thread pool threads available, then asynchronous code may be delayed.
Another part of the puzzle is that the thread pool has a limited thread injection rate. This is deliberate, so that the thread pool isn't constantly creating/destroying threads as its load varies. That would be very inefficient. Instead, a thread pool that has all of its threads busy (and still has more work to do) will only add a thread every few seconds.
The final concept to recognize is that Lazy<T> is blocking when using the default LazyThreadSafetyMode.ExecutionAndPublication behavior. The way this Lazy<T> works is that only one thread executes the delegate (() => InitializeContainer().GetAwaiter().GetResult()). All other threads block, waiting for that delegate to complete.
So now, putting it all together:
A large number of work items are placed onto the thread pool work queue (by Task.Run). The thread pool begins executing only as many work items as it has threads.
Each of these work items accesses the Container (i.e., Lazy<Container>.Value), so each one of these work items blocks a thread until the initialization is complete. Only the first work item accessing Container will run the initialization code.
The (asynchronous) initialization code attempts to make progress, but it needs a thread pool thread to be free in order to handle housekeeping when its awaits complete. So it is also queueing very small work items to the thread pool as necessary.
The thread pool has more work than it can handle, so it begins adding threads. Since it has a limited thread injection rate, it will only add a thread every few seconds.
The thread pool is overwhelmed with work, but it can't know which work items are the important ones. Most of its work items will just block on the Lazy<T>, which uses up another thread. The thread pool cannot know which work items are the ones from the asynchronous initialization code that will free up the other work items (and threads). So most of the threads added by the thread pool just end up blocking on other work that is having a hard time to complete since there are no thread pool threads available.
So, let's talk solutions.
IMO, the easiest solution is to remove (most of) the blocking. Allow the initialization to be asynchronous by changing the lazy type from Lazy<Container> to Lazy<Task<Container>>. The Lazy<Task<T>> pattern is "asynchronous lazy initialization", and it works by Lazy-initializing a task.
The Lazy<T> part of Lazy<Task<T>> ensures that only the first caller begins executing the asynchronous initialization code. As soon as that asynchronous code yields at an await (and thus returns a Task), the Lazy<T> part is done. So the blocking of other threads is very brief.
Then all the work items get the same Task<T>, and they can all await it. A single Task<T> can be safely awaited any number of times. Once the asynchronous initialization code is complete, the Task<T> gets a result, and all the awaiting work items can continue executing. Any future calls to the Lazy<Task<T>>.Value will immediately get a completed Task<T> which takes no time at all to await since it is already completed.
Once you wrap your head around Lazy<Task<T>>, it's pretty straightforward to use. The only awkward part is that the code for the work items now have to await the shared asynchronous initialization:
public class Do
{
private Lazy<Task<Container>> lazyContainer;
private Task<Container> ContainerTask => lazyContainer.Value;
public Do()
{
lazyContainer = new Lazy<Task<Container>>(InitializeContainer);
}
public async Task<T> ReadItemAsync<T>(string id, string partitionKey)
{
// This is the awkward part. Until you get used to it. :)
var container = await ContainerTask;
var itemResponse = await container.ReadItemAsync<T>(id, new PartitionKey(partitionKey));
return itemResponse.Resource;
}
// other methods are unchanged.
}
I have an AsyncLazy<T> type in my AsyncEx library, which is essentially the same as Lazy<Task<T>> with a few usability enhancements.
More information on this pattern:
Asynchronous lazy initialization blog post.
Recipe 14.1 "Initializing Shared Resources" in my book Concurrency in C# Cookbook, 2nd edition.
The Lazy<Task<T>> asynchronous lazy initialization pattern works great if you have a widely shared resource that may or may not need to be initialized. If you have a local resource (like a private member as in this example), and if you know you will always want it initialized, then you can make the code simpler by just using Task<T> instead of Lazy<Task<T>>:
public class Do
{
private Task<Container> ContainerTask;
public Do()
{
// Important semantic change:
// This begins initialization *immediately*.
// It does not wait for work items to request the container.
ContainerTask = InitializeContainer();
}
public async Task<T> ReadItemAsync<T>(string id, string partitionKey)
{
var container = await ContainerTask;
var itemResponse = await container.ReadItemAsync<T>(id, new PartitionKey(partitionKey));
return itemResponse.Resource;
}
// other methods are unchanged.
}

Start Service Bus Client from BackgroundService

I have a ServiceBusClient class that creates a QueueClient which is used to listen for messages on a bus. I have looked at the following articles to set this up:
Background tasks (Microsoft)
Hosted services (Microsoft)
Async and Await
My ServiceBusClient class that handles the QueueClient looks like this:
public class ServiceBusClient : IServiceBusClient
{
public ServiceBusClient(IEventService eventService, ServiceBusClientOptions options)
{
...
queueClient = new QueueClient(options.ConnectionString, options.QueueName);
}
public void Run()
{
RegisterOnMessageHandler();
}
private void RegisterOnMessageHandler()
{
...
queueClient.RegisterMessageHandler(ProcessMessagesAsync, messageHandlerOptions);
}
private async Task ProcessMessagesAsync(Message message, CancellationToken token)
{
var eventMessage = EventMessage.FromMessage(message);
await eventService.Write(eventMessage);
if (!token.IsCancellationRequested)
{
await queueClient.CompleteAsync(message.SystemProperties.LockToken);
}
}
private Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
{
// log errors
...
return Task.CompletedTask;
}
}
I was hoping to launch from an IHostedService or even by extending the BackgroundService. In the examples I find, work is constantly being executed in a while loop which does not fit my scenario since I am only trying to run a single command.
So I created a super simple implementation like this:
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
{
serviceBusClient.Run();
while (!cancellationToken.IsCancellationRequested)
{
// empty loop to keep running for lifetime of pod
}
}
If removing the async I obviously need to return something. I tried Task.CompletedTask but that required me to change the return type to Task<Task>.
If I have the async in place, I will need to await something, but I am not sure what.
This does not feel right. I would assume I would need to change something in the ServiceBusClient, but I am unsure what, since the ProcessMessagesAsync is async and does the heavy lifting in the background from my understanding.
All I want is for my web app to start listening for messages until it dies. How can I do that?
I gave up on using BackgroundService and implemented IHostedService instead.
public class MessageListenerService : IHostedService
{
private readonly IServiceBusClient client;
private readonly ITelemetryClient applicationInsights;
public MessageListenerService(IServiceProvider serviceProvider)
{
client = serviceProvider.GetService<IServiceBusClient>();
applicationInsights = serviceProvider.GetService<ITelemetryClient>();
}
public Task StartAsync(CancellationToken cancellationToken)
{
applicationInsights.TrackTrace(new TraceTelemetry("MessageListenerService is starting"));
client.Run();
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
applicationInsights.TrackTrace(new TraceTelemetry("MessageListenerService is stopping"));
return client.Stop();
}
}
If you find issues with this code please let me know in the comments and I'll update as appropriate.
In the end we created a console app for it anyway.

Application Insights Telemetry filtering is not working

I have already followed the guide here. I have tried both the config and "in code" approach of initializing and registering our telemetry processor. My goal is to filter out some HTTP responses so that those don't make their way to the sampled data. I haven't had any success. While our processor is initialized on app start, the Process method is never hit. Also, I already made sure that there is an InstrumentationKey in the config and that I'm using the correct key. What else am I missing?
This is what I have:
public class MyTelemetryProcessor : ITelemetryProcessor
{
private ITelemetryProcessor Next { get; set; }
// You can pass values from .config
public string MyParamFromConfigFile { get; set; }
// Link processors to each other in a chain.
public MyTelemetryProcessor(ITelemetryProcessor next)
{
this.Next = next; <-- this is always hit indicating this processor is active
}
public void Process(ITelemetry item)
{
// To filter out an item, just return
if (!OKtoSend(item)) { return; } <-- breakpoint here is never hit
// Modify the item if required
ModifyItem(item);
this.Next.Process(item);
}
private bool OKtoSend(ITelemetry item) <-- and consequently this method is never hit
{
var request = item as RequestTelemetry; <-- breakpoint here is never hit
// some more code goes here
return request.Success.GetValueOrDefault(false);
}
// Example: replace with your own modifiers.
private void ModifyItem(ITelemetry item)
{
item.Context.Properties.Add("app-version", "1." + MyParamFromConfigFile);
}
}
And this is how it is registered. I can see this being hit during debugging when the app starts up:
var builder = TelemetryConfiguration.Active.TelemetryProcessorChainBuilder;
builder.Use((next) => new MyTelemetryProcessor (next));
builder.Build();
In aspnetcore, my solution was to use :
services.AddApplicationInsightsTelemetryProcessor(typeof(BasicTelemetryFilter));
(using the regular CreateWebHostBuilder :
WebHost.CreateDefaultBuilder(args)
.UseApplicationInsights()
.UseStartup<Startup>();
)

WF 4 OnUnhandledException not hit

I've created a custom activity which contains as a Body another Activity.
[Browsable(false)]
public Activity Body { get; set; }
protected override void Execute(NativeActivityContext context)
{
ActivityInstance res = context.ScheduleActivity(Body, new CompletionCallback(OnExecuteComplete), OnFaulted);
}
private void OnFaulted(NativeActivityFaultContext faultContext, Exception propagatedException, ActivityInstance propagatedFrom)
{
throw new Exception(propagatedException.Message);
}
When an exception is thrown during the execution of the Body, ma handler for the OnFaulted is hit.
My execution starts with a call to static method Run of the WorkflowApplication class. My WorkflowApplication instance has a handler associated for the OnUnhandledException event.
instance.OnUnhandledException +=
delegate(WorkflowApplicationUnhandledExceptionEventArgs args)
{
Console.WriteLine(args.ExceptionSource);
waitEvent.Set();
return UnhandledExceptionAction.Cancel;
};
But regardless of what happens when the Activity hosted in the Body is executed, i never reach the handler defined above. I thought that if i throw an exception from the OnFaulted, i will be able to redirect the flow to the OnUnhandledException but i was wrong. Any ideas ?
I need this in order to centralize my errors, check them and display messages accordingly. Also i need a way to stop the execution and so on and i don't want to define handlers all over the application. Is there any way to accomplish this ?
As Will suggested, i will post what i did to handle my scenario.
Basically, in my custom activity i have hosted an Assign :
[Browsable(false)]
public Activity Body { get; set; }
Activity System.Activities.Presentation.IActivityTemplateFactory.Create(System.Windows.DependencyObject target)
{
return new Assignment()
{
Body = new Assign() { DisplayName = "" }
};
}
I've added this code to my Execute method :
ActivityInstance res = context.ScheduleActivity(Body, new CompletionCallback(OnExecuteComplete), OnFaulted);
I was trying to run this Assignment by giving an array a negative value as index and and an exception was thrown. This, somehow ended my execution but no handler for the events of my WorkflowApplication instance were hit.
Here is the method given as a callback when executing the body ( in our case the Assign activity ) :
private void OnFaulted(NativeActivityFaultContext faultContext, Exception propagatedException, ActivityInstance propagatedFrom)
{
faultContext.HandleFault();
CommunicationExtension ce = faultContext.GetExtension<CommunicationExtension>();
ITextExpression toTextExpression = (propagatedFrom.Activity as Assign).To.Expression as ITextExpression;
string valueTextExpression = string.Empty;
if ((propagatedFrom.Activity as Assign).Value != null)
{
if ((propagatedFrom.Activity as Assign).Value.Expression != null)
valueTextExpression = (propagatedFrom.Activity as Assign).Value.Expression.ToString();
}
if (ce != null)
{
ce.AddData(string.Format("{0} found on Assignment definition [{1} = {2}]", propagatedException.Message, toTextExpression.ExpressionText, valueTextExpression));
}
}
The trick was to call :
faultContext.HandleFault();
and use CommunicationExtension to allow me to to display the erros in the GUI.
The code for this class is trivial :
public class CommunicationExtension
{
public List<string> Messages { get; set; }
public CommunicationExtension()
{
Messages = new List<string>();
}
public void AddData(string message)
{
if (string.IsNullOrEmpty(message))
return;
Messages.Add(message);
}
}
Use this to add the extension:
CommunicationExtension ce = new CommunicationExtension();
instance.Extensions.Add(ce);
where instance is my WorkflowApplication instance.
I understood that for each instance of the workflow application we have one instance of its extension class. So i can send messages like this from all my custom activities in order to display their status.
I hope this scenario can help other people too.

Synchronous responses to `Gdx.net.sendHttpRequest` in LibGDX

I'm making a small game in LibGDX. I'm saving the player's username locally as well as on a server. The problem is that the application is not waiting for the result of the call so the online database's ID is not saved locally. Here's the overall flow of the code:
//Create a new user object
User user = new User(name);
//Store the user in the online database
NetworkService networkService = new NetworkService();
String id = networkService.saveUser(user);
//Set the newly generated dbase ID on the local object
user.setId(id);
//Store the user locally
game.getUserService().persist(user);
in this code, the id variable is not getting set because the saveUser function is returning immediately. How can I make the application wait for the result of the network request so I can work with results from the server communication?
This is the code for saveUser:
public String saveUser(User user) {
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("action", "save_user");
parameters.put("json", user.toJSON());
HttpRequest httpGet = new HttpRequest(HttpMethods.POST);
httpGet.setUrl("http://localhost:8080/provisioner");
httpGet.setContent(HttpParametersUtils.convertHttpParameters(parameters));
WerewolfsResponseListener responseListener = new WerewolfsResponseListener();
Gdx.net.sendHttpRequest (httpGet, responseListener);
return responseListener.getLastResponse();
}
This is the WerewolfsResponseListener class:
class WerewolfsResponseListener implements HttpResponseListener {
private String lastResponse = "";
public void handleHttpResponse(HttpResponse httpResponse) {
System.out.println(httpResponse.getResultAsString());
this.lastResponse = httpResponse.getResultAsString();
}
public void failed(Throwable t) {
System.out.println("Saving user failed: "+t.getMessage());
this.lastResponse = null;
}
public String getLastResponse() {
return lastResponse;
}
}
The asynchrony you are seeing is from Gdx.net.sendHttpRequest. The methods on the second parameter (your WerewolfsResponseListener) will be invoked whenever the request comes back. The success/failure methods will not be invoked "inline".
There are two basic approaches for dealing with callbacks structured like this: "polling" or "events".
With polling, your main game loop could "check" the responseListener to see if its succeeded or failed. (You would need to modify your current listener a bit to disambiguate the success case and the empty string.) Once you see a valid response, you can then do the user.setId() and such.
With "events" then you can just put the user.setId() call inside the responseListener callback, so it will be executed whenever the network responds. This is a bit more of a natural fit to the Libgdx net API. (It does mean your response listener will need a reference to the user object.)
It is not possible to "wait" inline for the network call to return. The Libgdx network API (correctly) assumes you do not want to block indefinitely in your render thread, so its not structured for that (the listener will be queued up as a Runnable, so the earliest it can run is on the next render call).
I would not recommend this to any human being, but if you need to test something in a quick and dirty fashion and absolutely must block, this will work. There's no timeout, so again, be prepared for absolute filth:
long wait = 10;
while(!listener.isDone())
{
Gdx.app.log("Net", "Waiting for response");
try
{
Thread.sleep(wait *= 2);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public static class BlockingResponseListener implements HttpResponseListener
{
private String data;
private boolean done = false;
private boolean succeeded = false;
#Override
public void handleHttpResponse(HttpResponse httpResponse)
{
Gdx.app.log("Net", "response code was "+httpResponse.getStatus().getStatusCode());
data = httpResponse.getResultAsString();
succeeded = true;
done = true;
}
#Override
public void failed(Throwable t)
{
done = true;
succeeded = false;
Gdx.app.log("Net", "Failed due to exception ["+t.getMessage()+"]");
}
public boolean succeeded()
{
return succeeded;
}
public boolean isDone()
{
return done;
}
public String getData()
{
return data;
}
}

Resources