8

Environment:

  • Windows Server 2003 - IIS 6.x
  • ASP.NET 3.5 (C#)
  • IE 7,8,9
  • FF (whatever the latest 10 versions are)

User Scenario:

User enters search criteria against large data-set. After initiating the request, they are navigated to a results page, where they wait until the data is loaded and can then refine the data.

Technical Scenario:

After user sends search criteria (via ajax call), UI calls back-end service. Back-end service queries transactional system(s) and puts the resulting data into a db "cache" - a denormalized table, set-up for further refining the of the data (i.e. sorting, filtering). UI waits until the data is cached and then upon getting notified that the process is done, navigates to a resulting page. The resulting page then makes a call to get the data from the denormalized table.

Problem:

The search is relatively slow (15-25 seconds) for large queries that end up having to query many systems based on the criteria entered. It is relatively fast for other queries ( <4 seconds).

Technical Constraints:

  1. We can not entirely re-architect this search / results system. There are way to many complexities here between how the UI and the back-end is tied together. The page is required (because of constraints that can not be solved on StackOverflow) to turn after performing the search criteria.

  2. We also can not ask the organization to denormalize the data prior to searching because the data has to be real-time, i.e. if a user makes a change in other systems, the data has to show up correctly if they do a search afterwards.

Process that I want to follow:

  1. I want to cheat a little. I want to issue the "Cache" request via an async HttpHandler in a fire-forget model.

  2. After issuing the query, I want to transition the page to the resulting page.

  3. On the transition page, I want to poll the "Cache" table to see if the data has been inserted into it yet.

  4. The reason I want to do this transition right away, is that the resulting page is expensive on itself (even without getting the data) - still 2 seconds of load time before even getting to calling the service that gets the data from the cache.

Question:

Will the ASP.NET thread that is called via the async handler reliably continue processing even if I navigate away from the page using a javascript redirect?

Technical Boundaries 2:

Yes, I know... This search process does not sound efficient. There is nothing I can do about that right now. I am trying to do whatever I can to get it to perform a little better while we continue researching how we are going to re-architect it.

If your answer is to: "Throw it away and start over", please do not answer. That is not acceptable.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Jamie Gunn
  • 83
  • 1
  • 5
  • Ok, let me see if i got it. When the users sends some search criteria, you will start the query execution asynchronously and immediately redirect the user to the results page. Then, on the results page you will load the page and keep verifying if the query is over on the server to show the results for the user. And you are asking if the async query execution would continue to run if the user exits the results page? Is that correct? – Mateus Schneiders Feb 11 '13 at 01:51
  • That is almost correct. The question is not will it continue running if the user leaves the results page, but rather will it continue running as the user is transferred to the results page. In my testing on my local machine, the async operation appears to continue running. However, I want to verify how reliable that process is. Is this the designed behavior of ASP.NET or a case of "it works on my machine"? – Jamie Gunn Feb 11 '13 at 01:55
  • If you're using the Threading namespace (are you?) to run some processing asynchronously on the Web Server, i don't think it would be a "it works on my machine" case. It should definitely work as expected on IIS as well. – Mateus Schneiders Feb 11 '13 at 02:11
  • Is it an option for you to use Threading instead of a HttpHandler? – Mateus Schneiders Feb 11 '13 at 02:18
  • We could thread (and would be by using a async handler), but whether we use a Page or a Handler, something has to catch the initial ajax call. We could even forget the async handler and use a regular generic handler. – Jamie Gunn Feb 11 '13 at 02:28

3 Answers3

4

Yes.

There is the property Response.IsClientConnected which is used to know if a long running process is still connected. The reason for this property is a processes will continue running even if the client becomes disconnected and must be manually detected via the property and manually shut down if a premature disconnect occurs. It is not by default to discontinue a running process on client disconnect.

Reference to this property: http://msdn.microsoft.com/en-us/library/system.web.httpresponse.isclientconnected.aspx

update

FYI this is a very bad property to rely on these days with sockets. I strongly encourage you to do an approach which allows you to quickly complete a request that notes in some database or queue of some long running task to complete, probably use RabbitMQ or something like that, that in turns uses socket.io or similar to update the web page or app once completed.

King Friday
  • 25,132
  • 12
  • 90
  • 84
  • Thank you for the link. I accepted your response. The only question that remains is that I can seem to find this logic "he reason for this property is a processes will continue running even if the client becomes disconnected and must be manually detected via the property and manually shut down if a premature disconnect occurs. " on that source. Essentially, you are stating that once a thread starts it will finish unless something exceptional happens. – Jamie Gunn Feb 11 '13 at 04:02
  • Yes. This is what I've experienced in practice as well. For example, I wrote a long running process that was initiated by a web page hit. A static member was toggled to indicate if the process was running or not. The the page request would respond as "ingest is still in process, try again later" if the static flag was true. I could go and come back in the same browser window and the process would not disconnect and it behaved as expected to run like a normal stateful program while the process was occurring and would reliably flip the flag back to false when completed (assuming try-catch). – King Friday Feb 11 '13 at 04:11
3

How about don't do the async operation on an ASP.NET thread at all? Let the ASP.NET code call a service to queue the data search, then return to the browser with a token from the service, where it will then redirect to the result page that awaits the completed result? The result page will poll using the token from the service.

That way, you won't have to worry about whether or not ASP.NET will somehow learn that the browser has moved to a different page.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
  • Another source was telling me about this type of solution. Essentially, we would have to have some type of background service (most likely outside of ASP.NET) that would be monitoring for added tokens, execute the search and then update the token that the search is done? This sounds great except for one small caveat. We do not want to slow down the "fast" searches (if possible). But, this may be the avenue that we have to go, if we want to create more consistency in our performance without huge architecture changes. I am still curious about the internals of the ASP.NET behavior. – Jamie Gunn Feb 11 '13 at 02:20
  • The service wouldn't have to "monitor". It would be a WCF service waiting for a request containing the search criteria. It would persist the criteria, return a token representing the request, then would begin processing the search. It would keep track of the progress of the search. When asked later for the progress, it would report on the progress. When complete, it would return the results of the search. – John Saunders Feb 11 '13 at 02:23
  • Also, if you can determine ahead of time that the "fast" search will be fast, then you can do that search "in-line". In fact, you could have the ASP.NET page wait a second or so, then ask the service whether it's done. If not, _then_ redirect to the "waiting for results" page. – John Saunders Feb 11 '13 at 02:24
  • That's interesting. There are ways we could predict if it is fast or not just by the search criteria. – Jamie Gunn Feb 11 '13 at 02:30
0

Another option is to use Threading (System.Threading).
When the user sends the search criteria, the server begins processing the page request, creates a new Thread responsible for executing the search, and finishes the response getting back to the browser and redirecting to the results page while the thread continues to execute on the server background.
The results page would keep verifying on the server if the query execution had finished as the started Thread would share the progress information. When it does finish, the results are returned when the next ajax call is done by the results page.

It could also be considered using WebSockets. In a sense that the Webserver itself could tell the browser when it is done processing the query execution as it offers full-duplex communications channels.

Mateus Schneiders
  • 4,853
  • 3
  • 20
  • 40
  • While I appreciate your answer, I am looking for an authoritative answer to, "Will the ASP.NET thread that is called via the async handler reliably continue processing even if I navigate away from the page using a javascript redirect?" – Jamie Gunn Feb 11 '13 at 02:34
  • The newly created thread is running alone on the server with no connection with the browser's page whatsoever (stateless). There's no relation between them that could cause the thread to terminate when the user redirects to another page. But i see i would need a source. – Mateus Schneiders Feb 11 '13 at 02:36