Background (Skip this part if you want)
Feel free to skip over this part if you choose, it's just some background for those who want to better understand the problem
At the beginning of one action on my site, I kick off several asynchronous operations. The action returns before the operations are complete. This is what I want. However, the View that gets loaded by this action invokes several other actions in a different controller. Some of these actions rely on the results of the async calls from the first page, so I need to be able to wait on the async calls to finish from the other controller. I thought about just using Session to store the WaitHandles, but as WaitHandles aren't serializable, I obviously can't do that.
Short version:
I need to be able to store an async WaitHandle object somewhere from one controller, such that it can be reliably retrieved in a different controller. These WaitHandles also need to be user-specific, but I can handle that part. Just don't list an option that would make doing that impossible.
Related
I am developing a C# desktop application (Windows Forms) with MVC and I want to use threads because I think it will provide me a more fluid interaction with the view to the final user, I will try to explain my best what I want.
I implemented MVC like this:
View -> has several controls that trigger events, these events are
subscribed by the controller
Controller -> receives some information from these events and passes
it to model by calling the adequate method, like this
Program.model.methodX(data)
Model -> processes the information and sends the data to the view by
triggering events that are subscribed by the view so it can update
itself
What the model actually does is communicate with a PLC to get some data from certain registers, while its doing this the view is freezed waiting for the reply.. I tried to implement threads in the model, because I think its the appropriate place for this, the problem is that I need to pass some information for the thread (number of registers etc) which is a problem because the thread wants a method that returns void and has no parameters (ThreadStart), and in the end send the data to the view by triggering an event which is a problem because it wants an object reference if it's a non-static method, field or property etc.. Is there any way I can achieve this or am I thinking all wrong?
Thank you all in advance.
I feel like you have a couple of questions in there, but I will try to address them:
You can pass parameters to a thread but you need to use ParameterizedThreadStart which allows the passing of an object.
In regards to passing data in and getting data back, you should probably look into using the TaskFactory and specifically the StartNew methods which will create a new Task. You can pass lambdas, methods that take parameters, and functions which will return a result and then you can use the task object to wait for and retrieve the result. For more info on threading including some insight into using the TaskFactory check out this link from Joseph Albahari on threading. It is an excellent resource.
In the general sense there are numerous techniques for getting data in and out of a thread. You can pass the this parameter in and then have access to all of its members, just remember that you are dealing with multiple threads and so need to be careful with reading/writing data. If there is shared data you will need to protect it with some form of locking. If you don't have to share the data while the thread is running, I would probably make a class to hold the data I need to pass that to the thread and do the same for the result. Then you can just use the TaskFactory.StartNew to launch the task and pass the data in and use the result of the task to get the data back out.
I'm starting to learn MVC.net and following this documentation.
In there, it is explained that an async controller will implement two methods, say the action is called News, then we will have a method called NewsAsync, which will return void, and a NewsCompleted, which will return a view, and that will be invoked once the outstanding operation returns.
My concern is that, i really don't see any point to an asynchronous operation that cannot return a view after the operation started. If the user will be unable to see any feedback whatsoever from the service until the asynchronous callback returns, then why bother with an asynchronous controller in the first place?
Is there any way to return an intermediate view after the async operation starts? Am i needlessly concerned about this apparent limitation? is there something i'm missing from the MVC.net?
The point of the asynchronous controller is to promote thread re-use so that if you have a particularly long running request that blocks on resources, you aren't going to be tying up the request queue. It has nothing to do with returning back information to the requesting party. To their end, they see no difference between an async controller and a normal controller.
It's not like it makes it more ajax friendly or whatever; a good example would be if you had a request start to render an image; traditionally, that request thread is going to be consumed while the CPU renders the image. With the asynchronous pattern, you can still be rendering the image, but that thread could be freed to service another web request until the render is complete, allowing greater throughput for your server.
One strategy is to set up polling on the client. Once the result has been generated the user will be notified.
i'm having an AsyncController that has 2 AsyncMethods.
One is called GetMessages, the other Check.
It seems, that one call blocks the other, probably because both call this.AsyncManager.OutstandingOperations.Increment();
Do they share the same AsyncManager?
What is the right way to do that?
Do i have to have 2 AsyncController to ensure that they dont get in each others way?
Update:
The code of both methods is similar to code posted here: Async operation completes, but result is not send to browser
in fact, it is the same controller, only added the Check/CheckCompleted.
sometimes, the "Check" has to get triggered so that the "GetMessages" returns
Update2: I have a waittimout of 60 seconds for both methods. I reduced one now to 5, this helps it, but i think it is just a hack.
They shouldn't block. The blocking you are observing might be due to the fact that both methods use Session and because Session is not thread safe, ASP.NET blocks access if you have two parallel requests from the same session (for example AJAX requests).
So try disabling all session for those actions by decorating them with the following attribute:
[SessionState(SessionStateBehavior.Disabled)]
I am using HttpWebRequest.BeginGetRequest() to make 500 asynchronous HTTP requests from a single method. I would like that method to wait until I get a response from all the requests or they timeout.
What is the best way to do this?
I'm currently wrapping the asynchronous calls within a List of Task objects to use Tasks.WaitAll(), but I don't want to go too far down the rabbit hole before I know that this is a good solution.
Any ideas?
EDIT
I implemented counters, and they work, but I'm curious about using delegates like shown on this page.
Multi-threading and Async Examples
Has anybody done something like this before? Is it overkill?
I'm currently wrapping the asynchronous calls within a List of Task objects to use Tasks.WaitAll()
This is a fairly clean solution if you truly want to force these "tasks" to synchronize and block at this point. This is the main rationale behind Task.WaitAll(), and is nice since it (optionally) allows you to cancel the blocking operation after a timeout, if you so choose.
Personally I wouldn't block the thread, it defeats the purpose of the async model.
If I absolutely had to wait for these web requests to finish before continuing I would instead keep a counter that is incremented each time you get called back on a successful or failed request.
Check the counter on each callback and if it has hit your desired count then let the thread continue...
This way you can also keep your UI nice and responsive and perhaps update a counter/progress bar - Even if you're not kicking these off on the UI thread it's nice to provide some visual feed back tot he user about what is going on.
What would be the best approach for implementing Tasks with a KEY that operate as follows:-
Option 1) Only one of this key is ever pending. Can be used, for example, from ASP.NET MVC to queue up a single render for a thumbnail image no matter how many times the image Url is hit. Only one runs, all other requests wait for that one to complete.
Option 2) All items with the same key must execute sequentially. Can be used for example to ensure that operations that fetch a file from a backing store to a local cache don't all try to get the file to the cache at the same time. Option 1 is a special case of this where subsequent actions with the same key are simply discarded (typically saves just a file-exists-check).
I have an existing WorkQueue that handles both of these cases (as well as Apartment state, ThreadPriority settings and maximum degrees of parallelism). TPL appears to be the best solution for replacing this and will bring improved cancellation options.
Nested Tasks with continuations look hopeful but maintaining a dictionary of currently queue'd tasks soon gets messy between the TaskFactory and the TaskScheduler classes. Inheriting from Task is problematic too since neither TaskFactory nor TaskScheduler are generic on Task.
Most Task Parallel examples assume that the set of tasks is known ahead of time. In this case new tasks are added all the time and need to be either discarded or chained onto existing tasks depending on the operation requested and the key passed in.
Has anyone implemented anything similar to this using TPL and if so, what approach did you take in your Task, TaskScheduler and TaskFactory classes?
Perhaps, one way that I can think of is
Create a wrapper class - say KeyProcessor to queue up items for a key.
KeyProcessor.Run() method will be capable of whatever queuing semantics that you need for. Essentially it would look for internal queue for any pending work and then keep doing it sequentially.
Maintain the dictionary of KeyProcessor objects.
For any new task, check in the dictionary for the same key. If does not exist then add it. Queue the task on it. If its not running then schedule it with TPL using Run method as action.
Use ContinueWith to schedule maintainer task - for example, whenever Task executing KeyProcessor.Run is completed, continuation tasks can check if there are any more tasks been scheduled for the same key (since it has completed) and start it again OR remove from dictionary.
All above would have been tricky from thread sync point not for few interesting collections present in System.Collections.Concurrent namespace. This would make the above logic much more simpler. For example, ConcurrentDictionary.GetOrAdd will allow to lookup and/or add the KeyProcessor object in thread-safe way.
This problem is similar to one I solved in ReactiveXaml, though mine also memoized previous requests. Take a look at the code for QueuedAsyncMRUCache (and its blog entry) - this code combines the TPL with the Reactive Extensions to get this kind of thing done, but it makes the important guarantee that the 2nd request for the same key will block on the first in-flight request instead of issuing another one.