I'm working on a multi-platform MVVM app, and I want to keep the ViewModel platform-agnostic.
I need to make use of DispatcherTimer or any other timer. Since the DispatcherTimer is not part of .NET Standard/Core, I was wondering if there are better alternatives to use so I can keep the VM clean of plat-specific code (I want it to depend only on .NET Core)?
The way it works is that the ViewModel implements an interface that exposes an event that the View is listening to, and responds to it accordingly.
The timer raises this event upon each tick.
The first option would be to just use classic Timer, which does fire on a non-UI thread and then just use Dispatcher manually in the consuming view. This is however not that convenient.
Other option would be to provide an interface, that consumers of your library could implement, which would have a method like RunOnUiThread(Action action) and which you would just use to make sure the view-specific code runs on the UI thread.
The best solution would probably be to get inspiration in Prism itself. For example the EventAggregator in the library can publish events on the UI thread - it first captures the current thread's synchronization context (see here on GitHub):
var syncContext = SynchronizationContext.Current;
This must be done for example during the View model construction, on the UI thread. And then you can invoke an action on this UI synchronization context even from another thread (see here on GitHub):
syncContext.Post((o) => action(), null);
This way you could just use one of the .NET Standard Timer classes and from their callback then use the SynchronizationContext to run an action on UI thread.
The other way you should know about DispatcherTimer is sometimes we may use DispatcherTimer to do something alternately.
We can use Task.Delay to replace DispatcherTimer sometimes.
Such as we need to run the code A every 5 seconds.
public async void Foo()
{
while (true)
{
// run a every 5 seconds
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(5));
A();
}
}
private void A()
{
}
And the A will run in the main thread if the main thread calls the Foo and I think you
can consider using this method in the framework.
Related
I'm trying to write a Vert.x Web handler that could be used to hide any processing latencies from an API to prevent figuring out existence of accounts as well as other information from an API. I would like to be able to just write something like:
router
.post("/uri")
.handler(new LatencyNormalizer())
.handler(new UriHandler());
In other words, make it as easy to use as possible and as easy to integrate into existing code bases as possible. Looking at the docs for Router and RoutingContext, I see only the following method as a possible candidate for implementing this:
https://vertx.io/docs/apidocs/io/vertx/ext/web/RoutingContext.html#addHeadersEndHandler-io.vertx.core.Handler-
I could then write code like:
public void handle(RoutingContext ctx) {
long start = System.nanoTime();
ctx.addHeadersEndHandler(v -> {
public void handle(RoutingContext ctx) {
long end = System.nanoTime();
Thread.sleep(...);
});
ctx.next();
}
Of course, this doesn't work, since sleep here blocks the thread. It looks like the handlers in the addHeaderEndHandlers list maintained internally by the RoutingContext are called synchronously, so there is no way to use e.g. vertx.SetTimer() inside the addHeaderEndHandler.
In other words, does Vert.x offer any interface that allows creating a handler which is called asynchronously before writing out to the wire (and with nothing written until the async call finishes)? This is for example how Netty works under the hood, which Vert.x leverages. I know I could implement this LatencyNormalizer as a base class for my other handlers, but it would not be as easy to integrate in existing code in that case.
I am adopting the new async/await Swift API. Things work great.
Currently in my apps I am using GCD serial queues as a pipeline to enforce tasks to happen serially.
For manipulating data of some critical models in the app I use a serial queue accessible from anywhere in the app:
let modelQueue = DispatchQueue(label: "com.myapp.updatemodelqueue")
Anytime a model needs to modify some model data I dispatch to that queue:
modelQueue.async {
// ... model updates
}
With the new async/await changes I am making I still want to force model actual updates to happen serially. So, for example, when I import new model data from the server I want to make sure they happen serially.
For example, I may have a call in my model that looks like this:
func updateCarModel() async {
let data = await getModelFromServer()
modelQueue.async {
// update model
}
}
Writing that function using that pattern however would not wait for the model update changes because of the modelQueue.async. I do not want to use modelQueue.sync to avoid deadlocks.
So then after watching WWDC videos and looking at documentation I implemented this way, leveraging withCheckedContinuation:
func updateCarModel() async {
let data = await getModelFromServer()
await withCheckedContinuation({ continuation in
modelQueue.async {
// update model
continuation.resume()
}
})
}
However, to my understanding withCheckedContinuation is really meant to allow us to incrementally transition to fully adopt the new async/await Swift API. So, it does not seem to be what I should use as a final approach.
I then looked into actor, but I am not sure how that would allow me to serialize any model work I want to serialize around the app like I did with a static queue like shown above.
So, how can I enforce my model around the app to do model updates serially like I used to while also fully adopting the new await/async swift API without using withCheckedContinuation?
By making the model an actor, Swift synchronizes access to it' shared mutable state. If the model is written like this:
actor Model {
var data: Data
func updateModel(newData: Data) {
data = newData
}
}
The updateModel function here is synchronous, it's execution is uninterrupted after it's invoked. Because Model is an actor, Swift restricts you to treat it as if you are calling an asynchronous funtion from the outside. You'd have to await, which results in suspension of your active thread.
If in case you'd want to make updateModel async, the code within will always be synchronous unless if you explicitly suspend it by calling await. The order of execution of multiple updateModel calls is not very deterministic. As far as you don't suspend within the updateModel block, it is sure that they execute serially. In such case, there is no use making the updateModel async.
If your update model code is synchronous you can make your model actor type to synchronize access. Actors in swift behave similar to serial DispatchQueue, they perform only one task at a time in the order of submission. However, current swift actors are re-entrant, which means if you are calling any async method actor suspends the current task until the async function completes and proceeds to process other submitted tasks.
If your update code is asynchronous, using an actor might introduce data race. To avoid this, you can wait for non-reentrant actor support in swift. Or you can try this workaround TaskQueue I have created to synchronize between asynchronous tasks or use other synchronization mechanisms that are also created by me.
I’m using Kotlin-Native with native-mt coroutine support and the Ktor library. I have several suspended functions that take in an object built using a builder pattern. I understand I need to call the suspended function on the main/ui thread. However, I can’t guarantee that the builder objects will be created on that thread. My understanding is they would need to be frozen before sending them to the main thread to be called with the suspended function. Is that correct?
For instance, this would fail because the query object hasn’t been frozen:
func loadData() {
DispatchQueue.global(qos: .background).async {
let query = CustomerQuery().emails(value: ["customer#gmail.com"])
self.fetchCustomersAndDoSomething(query: query)
}
}
func fetchCustomersAndDoSomething(query: CustomerQuery) {
DispatchQueue.main.async {
self.mylibrary.getCustomers(query: query) { response, err in
// do something with response
}
}
}
If that’s true, am I correct that I would need to add a method to every such object in order to ‘freeze’ it, since the freeze() Kotlin function from Freezing.kt doesn’t seem to be accessible from the Swift code importing my library? This is further complicated by the fact that freezing only applies to the iOS code, as the Android code doesn't need it.
Is there a simpler way to pass in Kotlin objects created by Swift to a suspended function, without requiring that those objects be created on the main thread?
In the Kotlin/Native world, whenever you are sharing objects between threads you have to make sure they are frozen (immutable), if you are not planning on making them #ThreadLocal. Android is an exception, since JVM is not that strict, and let's you share mutable objects between threads.
You have two options:
Either expose a freeze() function and use that
freeze() every incoming object in your shared code
Also if you don't freeze, probably you'll bump into IncorrectDereferenceException, which means you are trying to share mutable/non-frozen state
You don't freeze Swift classes. If CustomerQuery is a Kotlin class, you would need to freeze that.
However, you only need to call suspend functions on the main thread if you rely on the auto-generated Objc interface from the Kotlin compiler. We generally recommend not doing that because you can't control the lifecycle, but that's a whole different discussion.
I'm using GWTP, adding a Contract layer to abstract the knowledge between Presenter and View, and I'm pretty satisfied of the result with GWTP.
I'm testing my presenters with Mockito.
But as time passed, I found it was hard to maintain a clean presenter with its tests.
There are some refactoring stuff I did to improve that, but I was still not satisfied.
I found the following to be the heart of the matter :
My presenters need often asynchronous call, or generally call to objects method with a callback to continue my presenter flow (they are usually nested).
For example :
this.populationManager.populate(new PopulationCallback()
{
public void onPopulate()
{
doSomeStufWithTheView(populationManager.get());
}
});
In my tests, I ended to verify the population() call of the mocked PopulationManager object. Then to create another test on the doSomeStufWithTheView() method.
But I discovered rather quickly that it was bad design : any change or refactoring ended to broke a lot of my tests, and forced me to create from start others, even though the presenter functionality did not change !
Plus I didn't test if the callback was effectively what I wanted.
So I tried to use mockito doAnswer method to do not break my presenter testing flow :
doAnswer(new Answer(){
public Object answer(InvocationOnMock invocation) throws Throwable
{
Object[] args = invocation.getArguments();
((PopulationCallback)args[0]).onPopulate();
return null;
}
}).when(this.populationManager).populate(any(PopulationCallback.class));
I factored the code for it to be less verbose (and internally less dependant to the arg position) :
doAnswer(new PopulationCallbackAnswer())
.when(this.populationManager).populate(any(PopulationCallback.class));
So while mocking the populationManager, I could still test the flow of my presenter, basically like that :
#Test
public void testSomeStuffAppends()
{
// Given
doAnswer(new PopulationCallbackAnswer())
.when(this.populationManager).populate(any(PopulationCallback.class));
// When
this.myPresenter.onReset();
// Then
verify(populationManager).populate(any(PopulationCallback.class)); // That was before
verify(this.myView).displaySomething(); // Now I can do that.
}
I am wondering if it is a good use of the doAnswer method, or if it is a code smell, and a better design can be used ?
Usually, my presenters tend to just use others object (like some Mediator Pattern) and interact with the view. I have some presenter with several hundred (~400) lines of code.
Again, is it a proof of bad design, or is it normal for a presenter to be verbose (because its using others objects) ?
Does anyone heard of some project which uses GWTP and tests its presenter cleanly ?
I hope I explained in a comprehensive way.
Thank you in advance.
PS : I'm pretty new to Stack Overflow, plus my English is still lacking, if my question needs something to be improved, please tell me.
You could use ArgumentCaptor:
Check out this blog post fore more details.
If I understood correctly you are asking about design/architecture.
This is shouldn't be counted as answer, it's just my thoughts.
If I have followed code:
public void loadEmoticonPacks() {
executor.execute(new Runnable() {
public void run() {
pack = loadFromServer();
savePackForUsageAfter();
}
});
}
I usually don't count on executor and just check that methods does concrete job by loading and saving. So the executor here is just instrument to prevent long operations in the UI thread.
If I have something like:
accountManager.setListener(this);
....
public void onAccountEvent(AccountEvent event) {
....
}
I will check first that we subscribed for events (and unsubscribed on some destroying) as well I would check that onAccountEvent does expected scenarios.
UPD1. Probably, in example 1, better would be extract method loadFromServerAndSave and check that it's not executed on UI thread as well check that it does everything as expected.
UPD2. It's better to use framework like Guava Bus for events processing.
We are using this doAnswer pattern in our presenter tests as well and usually it works just fine. One caveat though: If you test it like this you are effectively removing the asynchronous nature of the call, that is the callback is executed immediately after the server call is initiated.
This can lead to undiscovered race conditions. To check for those, you could make this a two-step process: when calling the server,the answer method only saves the callback. Then, when it is appropriate in your test, you call sometinh like flush() or onSuccess() on your answer (I would suggest making a utility class for this that can be reused in other circumstances), so that you can control when the callback for the result is really called.
I would like to know the best practice to implement the follow scenarios.
public class MainWindow : Window
{
public void MainWorkflow()
{
// initiate a work-thread to run LongCompute
// when LongCompute finishes, update the corresponding GUI
// for example, change the statusbar as "Computation is done"
}
private void LongCompute()
{
// a 2-minute computation and then update member variables
// after it finishes. I expect the main thread to use the
// updated member variables to update GUI later
}
}
I am looking for a concrete good example to illustrate the best practice for this task.
As we know, the work-thread should not be used to update the GUI because GUI should be updated by the thread which created them. Also, I knew the following two modes:
Case I> The main thread waits for the worker thread and then update the GUI after than.
For example,
we can use the WaitOne method defined in AutoResetEvent in this case and it will be triggered by the Set method. But this is not a good way.
Case II> Set a callback function for the worker thread, however, the callback function is still called in the work thread which is not good for manipulating the GUI.
As #Jeff said in the comments, use a BackgroundWorker for this. You specify what function to call on the background thread, and another to call when the background work is done.