I'm new to async and need to consume an API that has it. I've read I should "go async all the way" back the UI command. So far I've propagated async back to my view model.
The code below blocks the Upload button in my UI. Is this because the RelayCommand's implementation calls it using await?
// In the ViewModel:
public MyViewModel()
{
...
UploadRelayCommand = new RelayCommand(mUpload, () => CanUpload);
...
}
private async void mUpload()
{
...
await mModel.Upload();
...
}
// In the model:
public async Task UploadToDatabase()
{
...
projectToUse = await api.CreateProjectAsync(ProjectName);
...
}
// In the API
public async Task<Project> CreateProjectAsync(Project project){}
Update: Sven's comment led me to find that CreateProjectAsync was running in a simulation mode that synchronously wrote to memory. When I wrapped that end code in Task.Run, it no longer blocked my Upload button. When not running in simulation mode, the API natively makes asynchronous calls to interact with a web server, so those also don't block.
Thanks.
The await itself will not block your UI. It is more likely that your Upload() method does not do any real asynchronous work.
(As Jim suggested, Task.Run() can be used in such a case. It will use the thread pool to run the operation in the background. Generally speaking, for IO-bound operations like uploads/downloads you should check if your API supports asynchronous calls natively. If such an implementation exists, it may make more efficient use of system resources than using a thread.)
Related
I checked the docs and stackoverflow but didn't find exactly a suiting approach.
E.g. this post seems very close: Dispatch a blocking service in a Reactive REST GET endpoint with Quarkus/Mutiny
However, I don't want so much unneccessary boilerplate code in my service, at best, no service code change at all.
I generally just want to call a service method which uses entity manager and thus is a blocking action, however, want to return a string to the caller immidiately like "query started" or something. I don't need a callback object, it's just a fire and forget approach.
I tried something like this
#NonBlocking
#POST
#Produces(MediaType.TEXT_PLAIN)
#Path("/query")
public Uni<String> triggerQuery() {
return Uni.createFrom()
.item("query started")
.call(() -> service.startLongRunningQuery());
}
But it's not working -> Error message returned to the caller:
You have attempted to perform a blocking operation on a IO thread. This is not allowed, as blocking the IO thread will cause major performance issues with your application. If you want to perform blocking EntityManager operations make sure you are doing it from a worker thread.",
I actually expected quarkus takes care to distribute the tasks accordingly, that is, rest call to io thread and blocking entity manager operations to worker thread.
So I must using it wrong.
UPDATE:
Also tried an proposed workaround that I found in https://github.com/quarkusio/quarkus/issues/11535 changing the method body to
return Uni.createFrom()
.item("query started")
.emitOn(Infrastructure.getDefaultWorkerPool())
.invoke(()-> service.startLongRunningQuery());
Now I don't get an error, but service.startLongRunningQuery() is not invoked, thus no logs and no query is actually sent to db.
Same with (How to call long running blocking void returning method with Mutiny reactive programming?):
return Uni.createFrom()
.item(() ->service.startLongRunningQuery())
.runSubscriptionOn(Infrastructure.getDefaultWorkerPool())
Same with (How to run blocking codes on another thread and make http request return immediately):
ExecutorService executor = Executors.newFixedThreadPool(10, r -> new Thread(r, "CUSTOM_THREAD"));
return Uni.createFrom()
.item(() -> service.startLongRunningQuery())
.runSubscriptionOn(executor);
Any idea why service.startLongRunningQuery() is not called at all and how to achieve fire and forget behaviour, assuming rest call handled via IO thread and service call handled by worker thread?
It depends if you want to return immediately (before your startLongRunningQuery operation is effectively executed), or if you want to wait until the operation completes.
If the first case, use something like:
#Inject EventBus bus;
#NonBlocking
#POST
#Produces(MediaType.TEXT_PLAIN)
#Path("/query")
public void triggerQuery() {
bus.send("some-address", "my payload");
}
#Blocking // Will be called on a worker thread
#ConsumeEvent("some-address")
public void executeQuery(String payload) {
service.startLongRunningQuery();
}
In the second case, you need to execute the query on a worker thread.
#POST
#Produces(MediaType.TEXT_PLAIN)
#Path("/query")
public Uni<String> triggerQuery() {
return Uni.createFrom(() -> service.startLongRunningQuery())
.runSubscriptionOn(Infrastructure.getDefaultWorkerPool());
}
Note that you need RESTEasy Reactive for this to work (and not classic RESTEasy). If you use classic RESTEasy, you would need the quarkus-resteasy-mutiny extension (but I would recommend using RESTEasy Reactive, it will be way more efficient).
Use the EventBus for that https://quarkus.io/guides/reactive-event-bus
Send and forget is the way to go.
I am quite a beginner with ReactiveUI and have a strange behavior with a ReactiveCommand.
I want to query data from a database that currently does not support
asynchronous operations. Since we want to exchange the database in the
future with an asynchronous interface I want to write everything as
if the database already would allow async operations. As far as I understand
that would mean that I wrap my database calls at the lowest level in
a Task.
I have a button which is bound to a ReactiveCommand and the command
starts the database query. While the query lasts I want to show some
sort of animation.
The problem is that whatever I tried, the query blocks my UI thread.
Here is part of my code:
public ReactiveCommand<Unit, Unit> StartExportCommand { get; }
//The constructor of my view model
public ExportDataViewModel(IDataRepository dr)
{
this.dr = dr;
//...
StartExportCommand = ReactiveCommand.CreateFromTask(() => StartExport());
//...
}
private async Task StartExport()
{
try
{
Status = "Querying data from database...";
//Interestingly without this call the Status message would not even be shown!
//The delay seems to give the system the opportunity to at least update the
//label in the UI that is bound to "Status".
await Task.Delay(100);
//### This is the call that blocks the UI thread for several seconds ###
var result = await dr.GetValues();
//do something with result...
Status = "Successfully completed";
}
catch(Exception ex)
{
Status = "Failed!";
//do whatever else is necessary
}
}
//This is the GetValues method of the implementation of the IDataRepository.
//The dictionary maps measured values to measuring points but that should not matter here.
//ValuesDto is just some container for the values.
public Task<IDictionary<int, ValuesDto>> GetValues()
{
//...
return Task<IDictionary<int, ValuesDto>>.Factory.StartNew(() =>
{
//### here is where the blocking calls to the database
//### specific APIs take place
return result;
}, TaskCreationOptions.LongRunning);
}
I don't understand why this code is blocking the UI thread although I am wrapping
the long running query in a Task.
Is there something wrong with this pattern or should I go another way with Observables?
Edit 1
I am aware of the fact that async != threads. I thought, however, that Task with the TaskCreationOptions.LongRunning would make the blocking code run on a thread pool thread.
Edit 2
As recommended by Andy I set a breakpoint inside my task and had a look into the Debug Threads window. It tells me that Task is running on a worker thread. Still my UI is blocking.
I have been slowly trying to convert my code from using action delegates to the new Tasks in my WPF application. I like the fact that an await operation can run in the same method, greatly reducing the number of methods I need, enhancing readability, and reducing maintenance. That being said, I am having a problem with my code when calling EF6 async methods. They all seem to run synchronously and are blocking my UI thread. I use the following technologies/frameworks in my code:
.NET Framework 4.5
WPF
MVVM Light 5.2
Generic Unit Of Work/Repository Framework v3.3.5
https://genericunitofworkandrepositories.codeplex.com/
Entity Framework 6.1.1
SQL Server 2008 R2 Express
As an example, I have a LogInViewModel, with a command that executes after a button is clicked on my WPF application. Here is the command as initialized in the constructor:
LogInCommand = new RelayCommand(() => ExecuteLogInCommand());
Here is the command body:
private async void ExecuteLogInCommand()
{
// Some code to validate user input
var user = await _userService.LogIn(username, password);
// Some code to confirm log in
}
The user service uses a generic repository object that is created using MVVM Light's SimpleIoC container. The LogIn method looks like this:
public async Task<User> LogIn(string username, string password)
{
User user = await _repository.FindUser(username);
if (user != null && user.IsActive)
{
// Some code to verify passwords
return user;
}
return null;
}
And my repository code to log in:
public static async Task<User> FindUser(this IRepositoryAsync<User> repository, string username)
{
return await repository.Queryable().Where(u => u.Username == username).SingleOrDefaultAsync();
}
The SingleOrDefaultAsync() call is Entity Framework's async call. This code is blocking my UI thread. I have read multiple articles from Stephen Cleary and others about async await and proper use. I have tried using ConfigureAwait(false) all the way down, with no luck. I have made my RelayCommand call use the async await keywords with no luck. I have analyzed the code and the line that takes the longest to return is the SingleOrDefaultAsync() line. Everything else happens almost instantaneously. I have the same problem when making other async calls to the DB in my code. The only thing that fixes it right away is the following:
User user = await Task.Run(() =>
{
return _userService.LogIn(Username, p.Password);
});
But I understand this should not be necessary since the call I am making to the database is IO bound and not CPU bound. So, what is wrong with my application and why is it blocking my UI thread?
Your RelayCommand is not async.
LogInCommand = new RelayCommand(() => ExecuteLogInCommand());
Because there is no async/await your ExecuteLogInCommand will be called synchronously.
You got to change it to
LogInCommand = new RelayCommand(async () => await ExecuteLogInCommand());
so that the RelayCommand is called async too.
Your LogIn and FindUser (which, according to the guidelines, should be called LogInAsync and FindUserAsync) which are not supposed to work with the UI should use ConfigureAwait(false) on all awaits.
However all calls are synchronous until something really asynchronous is called. I suppose that would be SingleOrDefaultAsync.
If wrapping it in Task.Run makes such a difference, then, for some reason, SingleOrDefaultAsync must be running synchronously.
I am creating a server which consumes commands from numerous sources such as JMS, SNMP, HTTP etc. These are all asynchronous and are working fine. The server maintains a single connection to a single item of legacy hardware which has a request/reply architecture with a custom TCP protocol.
Ideally I would like a single command like this blocking type method
public Response issueCommandToLegacyHardware(Command command)
or this asynchronous type method
public Future<Response> issueCommandToLegacyHardware(Command command)
I am relatively new to Netty and asynchronous programming, basically learning it as I go along. My current thought is that my LegacyHardwareClient class will have public synchronized issueCommandToLegacyHardware(Command command), will make a write to the client channel to the legacy hardware, then take() from a SynchronousQueue<Response> which will block. The ChannelInboundHandler in the pipeline will offer() a Response to the SynchronousQueue>Response> which will allow the take() to unblock and receive the data.
Is this too convoluted? Are there any examples around of synchronous Netty client implementations that I can look at? Are there any best practices for Netty?
I could obviously use just standard Java sockets however the power of Netty for parsing custom protocols along with the ease of maintaniability is far too great to give up.
UPDATE:
Just regarding the implementation, I used an ArrayBlockingQueue<>() and I used put() and remove() rather than offer() and remove(). Because I wanted to ensure that subsequent requests to the legacy hardware were only sent when any active requests had been replied to as the legacy hardware behaviour is not known with certainty otherwise.
The reason offer() and remove() did not work for me was that the offer() command would not pass anything if there was not an actively blocking take() request no the other side. The converse is true that remove() would not return anything unless there was a blocking put() call inserting data.
I couldn't use a put()/remove() since the remove() statement would never be reached since there was no request written to the channel to trigger the event from where the remove() would be called. I couldn't use offer()/take() since the offer() statement would return false since the take() call hadn't been executed yet.
Using the ArrayBlockingQueue<>() with a capacity of 1, it ensured that only one command could be executed at once. Any other commands would block until there was sufficient room to insert, with a capacity of 1 this meant it had to be empty. The emptying of the queue was done once a response had been received from the legacy hardware. This ensured a nice synchronous behaviour toward the legacy hardware but provided an asynchronous API to the users of the legacy hardware, for which there are many.
Instead of designing your application on a blocking manner using SynchronousQueue<Response>, design it in a nonblocking manner using SynchronousQueue<Promise<Response>>.
Your public Future<Response> issueCommandToLegacyHardware(Command command) should then use offer() to add a DefaultPromise<>() to the Queue, and then the netty pipeline can use remove() to get the response for that request, notice I used remove() instead of take(), since only under exceptional circumstances, there is none element present.
A quick implementation of this might be:
public class MyLastHandler extends SimpleInboundHandler<Response> {
private final SynchronousQueue<Promise<Response>> queue;
public MyLastHandler (SynchronousQueue<Promise<Response>> queue) {
super();
this.queue = queue;
}
// The following is called messageReceived(ChannelHandlerContext, Response) in 5.0.
#Override
public void channelRead0(ChannelHandlerContext ctx, Response msg) {
this.queue.remove().setSuccss(msg); // Or setFailure(Throwable)
}
}
The above handler should be placed last in the chain.
The implementation of public Future<Response> issueCommandToLegacyHardware(Command command) can look:
Channel channel = ....;
SynchronousQueue<Promise<Response>> queue = ....;
public Future<Response> issueCommandToLegacyHardware(Command command) {
return issueCommandToLegacyHardware(command, channel.eventLoop().newPromise());
}
public Future<Response> issueCommandToLegacyHardware(Command command, Promise<Response> promise) {
queue.offer(promise);
channel.write(command);
return promise;
}
Using the approach with the overload on issueCommandToLegacyHardware is also the design pattern used for Channel.write, this makes it really flexable.
This design pattern can be used as follows in client code:
issueCommandToLegacyHardware(
Command.TAKE_OVER_THE_WORLD_WITH_FIRE,
channel.eventLoop().newPromise()
).addListener(
(Future<Response> f) -> {
System.out.println("We have taken over the world: " + f.get());
}
);
The advantage of this design pattern is that no unneeded blocking is used anywhere, just plain async logic.
Appendix I: Javadoc:
Promise Future DefaultPromise
The following program hangs on the DoTheStuff().Wait(); line, if running as a Console application:
namespace Test
{
using System.Threading.Tasks;
using System.Windows.Forms;
class Program
{
static void Main(string[] args)
{
new Form();
DoTheStuff().Wait();
}
private static async Task DoTheStuff()
{
await Task.Delay(1000);
}
}
}
It works just as expected though, if you comment out the new Form(); line. (Runs for 1sec, then quits).
How can I keep the expected behaviour and still have a Form instance?
Now, some background if you are interested:
I have an application which is hosted as a windows service (as console when testing locally).
It requires to have access to the SystemEvents.TimeChanged event.
However, as per the documentation, this only works when having a windows Form (thus not in a service or console app). A workaround is presented in the linked documentation, and consists of creating a hidden form.
Unfortunately, the program now completely freezes instead, which is caused by the combination of await and having a Form instance.
So how on earth can I still have the expected async/await behaviour while accessing the SystemEvents.TimeChanged event?
Thanks to help below, here comes modified code which works without freeze:
namespace Test
{
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
class Program
{
static void Main(string[] args)
{
new Thread(() => Application.Run(new Form())).Start();
// SynchronizationContext.SetSynchronizationContext(null);
DoTheStuff().Wait();
}
private static async Task DoTheStuff()
{
await Task.Delay(1000);
}
}
}
In my program, I need to use "SynchronizationContext.SetSynchronizationContext(null);", since the threadpool should be used for awaiting tasks. I don't think that is a good practice, since Form obviously initialized it for a reason. But running the form hidden without user input (it is a service!), and can't see any harm right now.
The documentation feels a bit incomplete, with MS not even mentioning the issue that may arise using the example 2 (await/async implicitly changes behaviour when instantiating a Form).
This is by design. Creating a new Form object get the Winforms plumbing to install a new SynchronizationContext. Something you can see in the debugger by looking at the SynchronizationContext.Current property.
That property is big deal whenever you do anything asynchronously. If it is null, the default, then using await gets code to run on threadpool threads. If it is not then the await plumbing will implement the await by calling the SynchronizationContext.Post() method. Which ensures that your code runs on the main thread.
But that doesn't work in your program because you broke the contract. You didn't call Application.Run(). Required.
The SystemEvents class will create its own hidden notification window and pumps a message loop if you don't provide one. No need to create a form. The consequence is that its events will fire on an arbitrary thread, not your main thread. So do watch out for locking requirements.
The call to Wait causes a deadlock, as I explain on my blog and in a recent MSDN article.
In your case, you could use a simple MainAsync as such:
static void Main(string[] args)
{
MainAsync().Wait();
}
static async Task MainAsync()
{
new Form();
await DoTheStuff();
}
private static async Task DoTheStuff()
{
await Task.Delay(1000);
}
However, there are a couple of problems here. First, when you create a form (even a hidden form), you are expected to run an STA event loop, e.g., Application.Run. Second, as a Win32 service, you are expected to give your main thread back to the SCM, e.g., ServiceBase.Run.
So I would recommend a solution where you create a form and run an event loop on a secondary thread.