I have a checkbox list that each time the user selects one item, my ViewModel will ask my service to send the data related to that option.
_myService.GetAssetSpotDataCompleted += GetAssetSpotDataCompleted;
_myService.GetAssetSpotDataAsync(descItem);
Each selected item will call the same service Method and Debugging the service it sends back the right data.
My problem appears when the user checks some of the items while the data is not still received in my ViewModel. Example: the user selects item 1 and item 2, but my viewModel still has no answer from the service.
When my ViewModel receives the information comes the problem, I always receive twice the same data in my e.Result.
That means that it enters to the method GetAssetSpotDataAsync twice but always with the same result instead of the result for the item 1 and then for the item 2.
I have debugged everything and I have focused the problem in these first two lines of the method GetAssetSpotDataCompleted:
((MyServiceClient)sender).GetAssetSpotDataCompleted -= GetAssetSpotDataCompleted;
if (e.Result != null)
Anyone can help me with this?
What is happening is that by the time the response to first request has arrived the service finds 2 delegates listening on GetAssetSpotDataCompleted (one was added when the request was made the other when the second still outstanding request was made).
It will call both the delegates, it has no way to know that the second delegate was only meant for the second outstanding request. When the first is called its code removes one of the delegates from the event. When the second is called then it also removes the remaining delegate leaving the GetAssetSpotDataCompleted as null.
Now when the second request finally completes the service finds GetAssetSpotDataCompleted event is null and does nothing.
One solution would be to only add the event handler once, perhaps at the same point that _myService gets assigned in the ViewModel.
However there may be another issue, there is no guarantee that the responses to the two outstanding requests will arrive in the same order they were sent (although it highly likely that they will.) It may be better then to add an IsBusy boolean property to the ViewModel and set this true when an outstanding request is made, clearing it when completed. Bind this property to a BusyIndicator control (found in the Toolkit). This will prevent user interaction whilst an async operation that will ultimate change the state of the UI is in progress.
Related
I developed an asp.net solution for a customer some months ago, in which we're using AzureSearch in an input box. My approach was to send an ajax request once a second had transcurred since the last keystroke from the user. But our customer wanted it to always happen onchange of the input box, so we did that.
It has resulted in the client reporting a bug - inconsistent searches. It's because of a race condition, I logged the async calls and that's what happened. I'm thinking about adding a 0.5 sec delay to the javascript autocomplete. Or is there a better way? Like having a pool in javascript. The control we are using is jquery easy autocomplete.
What you're doing is called a "debounce". A debounce is when you have a timer start counting down when a user starts input. If they enter more input before the timer has finished, the timer is reset and starts counting down again. Only when the timer finishes does the AJAX call get made. In this case, a 200ms delay is what research has shown most people consider to still feel responsive.
However, if you really want results to pour in as the user is typing, what you need instead is called a "throttle". A throttle is similar to a debounce, except that it triggers at regular intervals, rather than waiting for the input to stop. To build one you'd still have a timer, however, you wouldn't reset it each time the user enters more input. Instead, you'd use a boolean to track whether or not new input had been entered. When the timer finishes, it checks if the boolean is true, if it is, set it to false and restart the timer counting down.
You could improve either method by keeping track of whether an AJAX call was already taking place. In both cases, if the timer runs out and the boolean tracking if a call is in progress is true, restart the timer.
Both a debounce and throttle are already available in several utility libraries such as lodash. You can use them to to wrap your existing event handlers.
var myInputChangeHandler = function() {
// do ajax call
};
// throttled handler will only be called every 200 ms...
var throttled = _.throttle(myInputChangeHandler, 200);
// ...no matter how many times this event fires
jQuery('input[type=text]').on('change', throttled);
In the end I did not need to add a delay or a throttle. By checking its official site, I discovered two very useful properties in jquery-easy-autocomplete, which are:
matchResponseProperty: To avoid race conditions, since the last ajax call musn't neccessarily be the last response from the backend service, it will take the last response which has a property named as specified with this attribute, which matches with the current text in the input.
listLocation: I was trying to render a json with an anonymous list of items and a property called InputPhrase, until I came to this, so I specified the list location in the base response object and used this model for the response.
public class SearchViewModel
{
public List<dynamic> Items { get; set; }
public string InputPhrase { get; set; }
}
Lastly, I set matchResponseProperty to "InputPhrase", and listLocation to "Items"
I have the following controller:
[HttpPost]
public ActionResult SomeMethod(string foo, obj bar)
{
//Some Logic
}
Now suppose that from the view that Action is called from a Button or from Ajax (with some edits), and I don't want to receive a double request.
What is the best approach to handle it from server side?
Update
You'd first have to define the time interval that would meet the
criteria of a double request – Jonesopolis
Let's suppose that in this case a double request are when the difference of time between first and 2nd call is less than 1s
Frankly, you can't, at least not totally. There's certain things you can do server-side, but none are fool-proof. The general idea is that you need to identity the POST is some way. The most common approach is to set a hidden input with a GUID or similar. Then, when a request comes in you record that GUID somewhere. This could be in the session, in a database, etc. Then, before processing the request, you check whatever datastore you're using for that GUID. If it exists, it's a duplicate POST, and if not, you can go ahead.
However, the big stipulation here is that you have to record that somewhere, and do that takes some period of time. It might only be milliseconds, but that could be enough time for a duplicate request to come in, especially if the user is double-clicking a submit button, which is most often the cause of a double-submit.
A web server just reponds to requests as they come in, and importantly, it has multiple threads and perhaps even multiple processes serving requests simultaneously. HTTP is a stateless protocol, so the server doesn't care whether the client has made the same request before, because it effectively doesn't know the client has made the same request before. If two duplicate requests are being served virtually simultaneously on two different threads, then it's a race to see if one can set something identifying the other as a duplicate before the other one checks to see if it's a duplicate. In other words, most of the time, you're just going to be out of luck and both requests will go through no matter what you try to do server-side to stop duplicates.
The only reliable way to prevent double submits is to disable the submit button on submit using JavaScript. Then, the user can effectively only click once, even if they double-click. That still doesn't help you if the user disables JavaScript, of course, but that's becoming more and more rare.
Look. Becareful with this approach. You will add most complexity to control this in server side.
First, you need recognize when the multiple requests are comming from the same user.
I don't think that to control this in server side is the best way.
However, if you really want that... look: https://stackoverflow.com/a/218919/2892830
In this link was suggested maintain a list of token. But, in your case, just check if the same token was received more than one time.
You need at least to implement double click on event listener.
UseSubmitBehiviar="false"
OnClientClick="this.disable='true'; this.value="Please wait";"
Check ASP.NET Life cycle
Check Request/Redirect
Add test code to see who is responsible
if (IsPostBack)
{
_CtrlName = thisPage.Request.Params.Get("__EVENTTARGET");
if (_CtrlName != null && _CtrlName == myButton.ID)
{
//Do your thing
}
}
Check IsPostBack in page load and use it correct to prevent dublicate requests.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
}
}
I have a scenario that I've tried to solve with TPL. The result is decent but I'm wondering if my design is flawed and if there is room for any improvement or radical changes.
Scenario:
An user can "subscribe" to X number of items and can set a given interval for updates of that item. The user will then get notifications if the item has changed its data. Since time is
a vital factor I want to show an item as updated straight away instead of waiting for all items to be updated and then notify the user about all updated items in a batch, or is this a bad idea?
My approach:
A user subscribes to an event called ItemUpdated.
A method, called Process is called each time with the given interval. The method is called in a fire and forget way by creating running it on a BackgroundWorker. The Process
method works in the following way:
2.1 Retrieve JSON strings and post them to a BufferBlock which is linked to a TransformBlock.
2.2 The TransformBlock parses each JSON string into a domain object called
Item. The TransformBlock is linked to an ActionBlock.
2.3 The ActionBlock invokes the event ItemUpdated for each Item it receives.
My question is basically: Is this an optimal solution or should i re-think my strategy? My biggest concern is that I notify the user about updated items with an event. Should I use an async callback method that will be given a list of all updated items instead or is there an alternative solution?
I have some nice, working edit-undo functionality in my winforms application. It works using a CommandStack class, which is two Stack<IStateCommand>s (one for undo, one for redo). Each command has an Execute and an Undo method, and the CommandStack object itself has an event that is fired when the stacks are changed.
The CommandStack also works out if the LogCommand method is called from its own Undo function, and therefore adding it to the redo stack, rather than the undo stack. This is done by simply adding the current ManagingThreadId to a List<int> object, then removing it after the Undo command is completed (as opposed to using the stack trace, which I believe would be much slower and a bit dirty).
There is a lot of different commands within my application so this formula is sort of set in stone as it'll take me a few days to redo all those IStateCommands implementations.
The only problem with this, currently, some UI events within also call other UI events, both of which log an IStateCommand to the undo history. Is there any way in C# that I can detect if the LogCommand function has already been called from the same UI event (Click, DragDrop, SelectedIndexChanged, TextChanged, etc), then I can combine the commands into one command (using my CommandList class, which also inherits IStateCommand)?
I've thought of saving the current time when the undo event was called, then if the next command is logged less than x milliseconds later, combine them in the history, but this seems a bit sloppy. I've also considered searching the stack trace, but I don't really know what to look for to find the root UI event, nor do I know whether I would tell the different between one button click, then a different click on the same button.
It may also be helpful to know that all of these commands are being called from the UI thread from event handlers (mostly from events from custom user controls). The only part of my application that uses another thread runs after most UI events, after the undo history is logged.
Thanks!
Sort Version
The same method is being called twice from the same UI event (eg, MouseUp, DragDrop). The second time this method is called, how do I check that it has already been called once by the same UI event?
Edit: The solution (sort of)
It's a bit of a dirty one as I don't have the time to completely re-write this system. However I've implemented it in such a way that gives the option not to be so dirty in the future.
The solution is based on one of Erno's comments on his answer (so I will mark his answer as accepted), where he suggests added a parameter. I added another overload to my LogCommand(IStackCommand) method in the CommandStack class, LogCommand(IStackCommand, string). The string is the actionId, which is stored for each command, and if this string is the same as the last, the commands are combined. This gives the option to go through each event and give a unique ID.
However, the dirty part - to get it working before we have to show the client, the actionId defaults to System.Windows.Forms.Cursor.Position.ToString(), ouch!! Since the cursor position is not changed while the UI thread is executing, this combines each command. It actually even combines TextChanged commands (as long as they don't move their mouse!)
It might be an option to add a local stack of called-commands to a command.
When a command executes other commands add the command to the local stack so you can undo the commands on this local stack when the command must be undone or redone.
EDIT
I am not quite sure what you don't understand.
I would simply add a CommandList property to the StateCommand. Everytime the StateCommand invokes/triggers another StateCommand it should add the new StateCommand to the CommandList. So the global CommandList keeps track of the Commands that can be undone from the UI and each StateCommand keeps track of the StateCommands it invoked (so these are not added to the global undo CommandList)
EDIT 2
If you can't or do not want to change to that setup you would have to pass a parameter to the execution of the commands that links them together.
Did you try to inspect the method stack and analyze it method-by-method:
StackTrace st = new StackTrace();
for ( int i=0; i<st.FrameCount; i++ )
{
StackFrame sf = st.GetFrame(i);
MethodBase mb = sf.GetMethod();
// do whatever you want
}
I don't know what you need exactly to achieve, but I implemented something similar, maybe you can get some ideas...
In summary, you can store some information in a ThreadStatic variable. Then, any time you want to log a command, inspect the thread static variable to find out the context in which you are logging the command. If it's empty, you are starting a new command logging sequence. If not, you are inside a sequence.
Maybe you can store the entry event (e.g. Click, DragDrop,...), or the command itself... It depends on your needs.
When the initial event callback is completed, clean the static variable to signal that the sequence has been completed.
I successfully implemented a similar strategy to track commands executed upon an object model. I encapsulated the logic within an IDisposable class that also implemented the reference counting to handle the nested usings. The first using started the sequence, subsequents using statements increased and decreased the reference counting to know when the sequence was completed. The outermost context disposing fired an event containing all the nested commands. In my specific case it has worked perfectly, I don't know if it may fulfill your needs...
Say I have 2 methods. One is an method triggered by the selected index changing in the listbox. The second method helps by clearing all textboxes, setting listbox index to -1, and setting the focus.
Question:
Method two executes, during the code it changes the selected index of the listbox to -1, thereby setting off the event trigger for the 1st method. Does Method 2 HALT it's own execution and transfer the process to the event, and then return back to its work after Method 1 is finished... OR does method 2 finish its entire codeblock then transfer to Method 1 since the selected index changes?
The first case.
Let's leave threads out of it for a moment, particularly because they're not involved in your scenario.
You're talking about properties and methods, but underneath it all, it's all just functions. When one function invokes another, control in your program transfers to the called function. When that function finishes running, control returns to the point where it was called. Your program automatically remembers where it needs to go back to, no matter how deeply functions call more functions.*
When your second function sets the index, what really happens is that the compiler translates the property-set operation into a function call. (Properties are ultimately just "syntactic sugar" for functions.) That function calls a bunch of other functions that aren't important to the scenario, except that one of them is the one that invokes the "index changed" event handler. It sees that you have a method associated with that event, and it calls your first method.
Your first method runs, and when it finishes, it returns to the "invoke the index-changed event handler" function. Eventually, that and all the other unimportant functions finish running (perhaps after making more function calls in sequence), and the "set the index property" function returns control to your second method.
You can prove to yourself that your first suggestion is how it works. Display a message box in your first method, and display another message box after the point in your second method where you set the index property. (Use different messages!) You should see the first message appear, and after you dismiss the message box, you should see the second message appear, thus showing that the second method did not continue executing while the first one was running.
* There is a limit, but it's rarely hit unless there's a bug in your program. When you have too many nested function calls, what happens is a stack overflow.
There's a third alternative you can explore: they can also run at the same time! If I understand your question correctly, method 2 would be triggered by the index change event. In a C# Windows Forms application, this other event would occur in a separate thread of execution.
Concepts to explore: threading.
I hope this gives you a starting point in your explorations of knowledge.
Assuming no multi-thread situation, the event will fire before he end of execution of the method. If you want to see this, code what you have suggested in a .NET language and examine the Il produced. You can do this with ILDASM, or Reflector, or even create your own relfletion application. You do have to understand the syntax of IL enough to see the branch, but it is not that difficult, as long as you understand programming concepts.
Rob has labeled this "syntactical sugar", which I will agree with somewhat. It is really a compiler trick, but I guess it falls under the label "syntactical sugar" as it is commonly used.
I assume the language in question is c# and you thus have a language that supports multiple threads. If you don't want to worry about threads (which would be a bad idea if you consider user experience) you can run your GUI in one thread and have the same behavior, unless the components create their own thread (which would be a bit weird though). If you want to achieve an asynchronous (parallel) execution of the event you need to have the the event triggering in its own thread.
To answer your question: if you aren't using multiple threads, the method triggered by the event will be queued. This is exactly what happens when you see GUI responding slowly in some programs.
Hope it cleared things out and welcome from another newcomer :)
I myself am a beginner, maybe I can help. Method2 would fire, then when the selection changes, Method1 would do his stuff, then Method2 would continue.
If you don't want Method1 to fire at that time, you might want to do is something like:
(REALLY pseudo code)
Method2(object sender, System.EventArgs e)
{
//Unsubscribe Method1 from ListboxEvent
Listbox.OnSelectionChange -= Method1;
... Stuff Method2 actually does ...
Manualy call Method1 if you want it to fire
//Subscribe Method1 from ListboxEvent
Listbox.OnSelectionChange += Method1;
}
It's probably not optimal (and maybe some Best Practices...) but for a lack of a better explanation, at least you have a bit of information to help you search. Hope it helps!