ASP.NET MVC Task.Run running status - asp.net-mvc

I want to run a task like below :
Task.Run(() => GetWeatherAsync());
And this task only sleeps for 20 seconds :
public async void GetWeatherAsync()
{
System.Threading.Thread.Sleep(20000);
}
I want to prevent new user to enter to this scope (Method) until the previous Process is running .
What happens if the current user is waiting in GetWeatherAsync and new user enter .

Using Task.Run doesn't make your method async. Just use the GetWeatherAsync method without another overhead (because it's already async) and ASP.NET runs each request in a new thread. You don't need another thread here.
You should not use async void.
You should not use Thread.Sleep in async methods. It's Task.Delay here.
You can use locking here to achieve your goal:
// only 1 thread can be granted access at a time
static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1,1);
public async Task GetWeatherAsync()
{
// If no-one has been granted access to the Semaphore, code execution will proceed,
// otherwise this thread waits here until the semaphore is released
await semaphoreSlim.WaitAsync();
try
{
await Task.Delay(20000); // Your code here
}
finally
{
semaphoreSlim.Release();
}
}
P.S.
You need to start reading this Persian course about C# 5, Async.

Related

How to simulate SessionStateBehavior.ReadOnly in .net core

i need to make parallel request in .net core.
In MVC is easy to do that with
SessionStateBehavior.ReadOnly
but i suppose we can not use in .net core app so How to simulate System.Web.SessionState.SessionStateBehavior.ReadOnly in .net core
i think i figure it.
We can not use SessionStateBehavior.ReadOnly but there is a new methor for make parallel requesting. Normaly session lock request queue and we have to wait request is finish and process to next request form queue.
But if we make Session load async with Session.LoadAsync() method than it's make requests parallel.
How We Do That
internal static async Task<int> GetSessionInt(this ISession session, string key)
{
await session.LoadAsync();
return session.GetInt32(key).Value;
}
Than call method from action
if action is async
int id = await HttpContext.Session.GetSessionInt("id");
if action is not async
int id = HttpContext.Session.GetSessionInt("id").Result;

Waiting for async to be completed

I currently have something like this
Future<bool> checkAvailability(String email) async {
var client = new http.Client();
var response = await client.get(host);
bool result;
if (response.statusCode == 404) {
result= true;
}
else if (response.statusCode == 200) {
result= false;
}
client.close();
return result;
}
I am calling the above method from a regular non-aysnc function
in this way
void test() {
checkAvailability(email).then((result){....}
);
}
The problem with the above code is that its async. From what I understand is that Once checkAvailability is called its launched in a different thread ? and the ui (main) thread continues? Am I correct?
What I would like to do is to have test function wait for the result of checkAvailability. I know I can use await but then the method test will need to be marked as async and when this method is called it will be launched in a different thread. What I want is for the call to checkAvailability be synchronous and I don't mind waiting for a response.
Once checkAvailability is called its launched in a different thread ?
Async execution is not related to threads, async works with an event queue https://webdev.dartlang.org/articles/performance/event-loop
test will need to be marked as async and when this method is called it will be launched in a different thread.
As mentioned before, it won't be another thread. Using async on a test method usually works fine. Why do you try to avoid it?
What I want is for the call to checkAvailability be synchronous and I dont mind waiting for a response.
If you don't care about the result, just don't await it, although this would also cause the calling code to continue before checkAvailability was completed.
What I want is for the call to checkAvailability be synchronous and I dont mind waiting for a response.
There is no way to go back from async execution to sync execution. Once an async call is made, it's completion and the result will always be a Future and needs to be awaited or handled by .then(...).
If you don't care when checkAvailability completes and don't need a result from async calls it makes, then you don't need to await or use then(...). Just call the method and that's it.

Run method on a separate thread inside Action

Suppose I have an Action like below that I want to return the View asap and continue doing some work in the background thread.
public async Task<ActionResult> Index()
{
Debug.WriteLine("Inside Index");
var newCustomer = new Customer
{
Name = "Ibrahim"
};
Task.Run(() => SaveCustomer(newCustomer));
Debug.WriteLine("Exiting Index");
return View();
}
private async Task SaveCustomer(Customer NewCustomer)
{
Debug.WriteLine("Started Saving Customer");
await Task.Delay(2000);
Debug.WriteLine("Completed Saving Customer");
}
I do get the output as intended which is:
Inside Index
Exiting Index
Started Saving Customer
Completed Saving Customer
But what bothers me is that I get a warning that my Index action will run synchronously regardless and I should put an await but then the view is returned after SaveCustomer is completed and the purpose is defeated.
How am I doing this wrong? Any suggestion is appreciated.
But what bothers me is that I get a warning that my Index action will run synchronously
How am I doing this wrong?
Don't force asynchrony from the top down. Instead, start with naturally-asynchronous operations at the lowest level (e.g., EF6 database access), and allow the asynchrony grow from the lowest-level code upward.
Also, on ASP.NET, you should strongly avoid Task.Run.
Applying these two principles results in an Index method like this:
public async Task<ActionResult> Index()
{
Debug.WriteLine("Inside Index");
var newCustomer = new Customer
{
Name = "Ibrahim"
};
await SaveCustomer(newCustomer);
Debug.WriteLine("Exiting Index");
return View();
}
but then the view is returned after SaveCustomer is completed and the purpose is defeated.
Not at all. The purpose of asynchronous ASP.NET code is not to return early to the client. async and await do not change the HTTP protocol. await on the server side yields to the thread pool, not the client.
If you need to return early (and most people don't - they only think they "need" to), then you should use one of the established patterns for returning early (as I describe on my blog). Note that the only proper (i.e., fully reliable) solution entails setting up a reliable queue with an independent background process.
Your Index does not make use of any async feature at all. Why did you mark it async? You must be misunderstanding something, not sure what. Remove the async Task specification.
You get that compiler warning because there is nothing asynchronous in your Index() method. Your Task.Run(() => SaveCustomer(newCustomer)); line means Fire And Forget (non awaited task) - this is very different than asynchronous code. Index() is completely synchronous, while creating a "side Task" to execute sometime in the future. As the other answer mentioned - you could just as well remove the async mark from your method - it's not async.

Struts2 JMS request processing long running process

I have a Struts2 Action class that places a JMS Fetch request for a list of Trade in a JMS Queue. This JMS Fetch message is processed by an external process and can take either a few seconds or even few minutes depending on the number of Trade files to be processed by the external task processing app.
I want to know how to handle this HTTP Request with an appropriate response. Does the client wait till the list of Trades is returned? (client (UI) has to action on it and has nothing else to do meanwhile).
The way I approached it is
HTTP Request -->
Struts2 Action -->
Invokes a Runnable to run in a separate Thread (separate from Action class)
UI waits
Action class thread sleeps till runnable does it's job
When Task completed, return list of Trades to UI
Flow is as follows:
Place JMS Fetch Request on Queue1
ExecutorService for Runnable
CClass cclass = new CClass();
final ExecutorService execSvc = Executors.newFixedThreadPool(1);
execSvc.execute(cclass);
Where CClass implements runnable returning a list of Trades:
List<Trade> tradesList = new ArrayList<Trade>();
#Override
public void run() {
while (true) {
try {
Message message = msgConsumer.receive(); // SYNCHRONOUS / NO MDB
if (message == null){
break;
}
if (message instanceof TextMessage) {
TextMessage txtMessage = (TextMessage) message;
Trade trade = TradeBuilder.buildTradeFromInputXML(txtMessage);
if (trade != null) {
tradesList.add(trade); // tradeList is a CClass class variable
}
}
} catch (JMSException e) {
logger.error("JMSException occurred ", e);
}
}
closeConnection();
}
And while this runnableis executing, I do a Thread.sleep in Action class (to let the Runnable execute in the separate Thread)
// In Action class
try {
Thread.sleep(5000); // some time till when the runnable will get executed
} catch (InterruptedException e) {
e.printStackTrace();
}
execSvc.shutdown();
Problem is If I use Callable with a FutureTask and do a get() , that will be blocking till any result is returned. If I do a Runnable, I have to put Action class Thread to sleep till runnable has executed and tradeList is available.
Using Runnable approach, I am able to get couple of hundred records back to UI giving a 5 second Thread.sleep() in main Action class, but only partially constructed tradeList when thousands of records are to be fetched and shown in UI.
This is clearly Not a fail-proof approach.
Any better approach to suggest ? Please elucidate steps for processing in one complete request - response flow.
Yes there is a much better approach when making a standard HTTP request (with ajax you can do other things).
You want to look at the Struts2 Execute and Wait Interceptor Which has most of the functionality you've already implemented. Also look at the token interceptor... which could be useful (it prevents duplicate requests, but doesn't provide a happy wait screen like exec and wait does).

WebClient async callback not called in ASP.NET MVC

On GET request I run (something like):
public ActionResult Index(void) {
webClient.DownloadStringComplete += onComplete;
webClient.DownloadStringAsync(...);
return null;
}
I see that onComplete isn't get invoked until after Index() has finished execution.
I can see that onComplete is invoked on a different thread from one Index was executed on.
Question: why is this happening? why is webClient's async thread is apparently blocked until request handling thread is finished?
Is there a way to fix this without starting new thread from ThreadPool (I tried this, and using thread pool does work as expected. Also webClient's callback does happen as expected if DownloadStringAsync is called from a ThreadPool's thread).
ASP.NET MVC 3.0, .NET 4.0, MS Cassini dev web server (VS 2010)
EDIT: Here is a full code:
public class HomeController : Controller {
private static ManualResetEvent done;
public ActionResult Index() {
return Content(DownloadString() ? "success" : "failure");
}
private static bool DownloadString() {
try {
done = new ManualResetEvent(false);
var wc = new WebClient();
wc.DownloadStringCompleted += (sender, args) => {
// this breakpoint is not hit until after Index() returns.
// It is weird though, because response isn't returned to the client (browser) until this callback finishes.
// Note: This thread is different from one Index() was running on.
done.Set();
};
var uri = new Uri(#"http://us.battle.net/wow/en/character/blackrock/hunt/simple");
wc.DownloadStringAsync(uri);
var timedout = !done.WaitOne(3000);
if (timedout) {
wc.CancelAsync();
// if this would be .WaitOne() instead then deadlock occurs.
var timedout2 = !done.WaitOne(3000);
Console.WriteLine(timedout2);
return !timedout2;
}
return true;
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
return false;
}
}
I was curious about this so I asked on the Microsoft internal ASP.NET discussion alias, and got this response from Levi Broderick:
ASP.NET internally uses the
SynchronizationContext for
synchronization, and only one thread
at a time is ever allowed to have
control of that lock. In your
particular example, the thread running
HomeController::DownloadString holds
the lock, but it’s waiting for the
ManualResetEvent to be fired. The
ManualResetEvent won’t be fired until
the DownloadStringCompleted method
runs, but that method runs on a
different thread that can’t ever take
the synchronization lock because the
first thread still holds it. You’re
now deadlocked.
I’m surprised that this ever worked in
MVC 2, but if it did it was only by
happy accident. This was never
supported.
This is the point of using asynchronous processing. Your main thread starts the call, then goes on to do other useful things. When the call is complete, it picks a thread from the IO completion thread pool and calls your registered callback method on it (in this case your onComplete method). That way you don't need to have an expensive thread waiting around for a long-running web call to complete.
Anyway, the methods you're using follow the Event-based Asynchronous Pattern. You can read more about it here: http://msdn.microsoft.com/en-us/library/wewwczdw.aspx
(edit) Note: Disregard this answer as it does not help answer the clarified question. Leaving it up for the discussion that happened under it.
In addition to the chosen answer, see this article for further details on why the WebClient captures the SynchronizationContext.
http://msdn.microsoft.com/en-gb/magazine/gg598924.aspx

Resources