Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

asp.net C# ajax running 'async' batch job

I'm quite new to asp.net and C# so bear with me. Also my apologies if this have been asked before... if so please direct me to a page which is of help.

What I have:

  • A page: With 4 updatepanels

    1. 1st UpdatePanel which contains a (item) gridview, user display options (not important to this question) and button which perform a database search which returns a list of items displayed to the grid. User selects an item on this grid...

    2. 2nd UpdatePanel contains a dropdownlist containing a list of available task loaded from an XML. User will select a task, which displays a bunch of available options/parameters (also loaded from XML file) to another (parameter) gridview in 2nd updatepanel. Gridview here will always have one row of data. I'm using gridview here because it is easier rather than creating dynamic controls (paramaters are different to each task ). User is able to enter parameter values into the grid. User clicks on an Add button and the the task is added to another gridview in the 3rd updatepanel.

    3. 3rd UpdatePanel contains a (task) gridview which contains all the task added by user. There's also a button which is suppose to batch run all the task. When the button is clicked, it goes through the (task) gridview looking for pending task to run. For each pending task, it calls a web service which handles the task appropriately. Web service returns the task result together with log output.

    4. 4th UpdatedPanel for now just contains a div that displays the log output returned from web service.

What I want to further work on and not know how is:

  • how do I perform an 'asynchronous' batch job? What i'm trying to achieve is that, when user clicks on the batch run button, the 3rd (task) updatepanel together with all it's control get disabled while the batch jobs run 'behind the scene'. Depending on the task, each task could take up to 5seconds each. If user had created 60 tasks, I would think this will also cause the page to timeout?
  • While the batch job is running, user can further search for other items in (item) UpdatePanel and add new tasks using (parameter) updatepanel to (task) updatepanel.
  • (Task) UpdatePanel will be showing a 'Job in progress...' overlay of some sort when job is running.

Hope you understand my question. Much appreciated if someone could be kind enough to give some guidance and/or directions on how to tackle this task

Further info:

Using Framework 3.5

Using Asp.net C# + Ajax

Web Service is of gSoap on a solaris box

Many thanks in advance.


Sorry for being a noob, i was trying to reply to your help but found that there's a limited of characters i can put in. I'll just update my own comments for now.

Thanks for your suggestion. Sorry for the late response, I've been looking around the other day and had made some changes, getting it to work with 'PageAsyncTask' and 'IAsyncResult'. I've created a web service class which will be called by the page. The new web service class will than called the gSoap web service. I've managed to some sort of running it 'asynchronously'.

I have a button which executes:

  protected void StartASyncJob()
  {
     PageAsyncTask task = new PageAsyncTask(
        new BeginEventHandler(BeginAsyncCommandTask),
        new EndEventHandler(EndAsyncCommandTask),
        new EndEventHandler(AsyncCommandTaskTimeOut), null);

     RegisterAsyncTask(task);
  }

BeginAsyncCommandTask will go through the grid, get the first pending task and calls the web service.

EndAsyncCommandTask will then retrieve the return results, writes out the (log) UpdatePanel. It will then execute StartASyncJob() again looking for the next pending record to process.

All this works ONLY if don't do anything else on the page. If I was (while the asynchronous process was running ) to do a search for more items in (item) gridview or select a new task from (task) dropdownlist, the event will not fire till the asynchronous web service process has completed. And when it's completed, the dropdownlist or search event fires, my log details returned from the web service is not updated.

I guess the 'wait' is caused by 'PageAsyncTask' being 'spawn' from the same page thread?

I would have thought having the 'asynchronous' web service will enable the user to do more than one thing at a time giving better user experience. But it seems I'm wrong and/or have not done it right.

I have not tried your suggestion of using QueueUserWorkItem; but before I do, may i ask if it will give the same effect as using 'PageAsyncTask'. Will using QueueUserWorkItem has the same effect of 'spawning from same page thread' ?

Many thanks in advance. Sorry if i've not explained myself well and please do let me know if you need me to post my code.

like image 616
user1905597 Avatar asked Nov 03 '22 08:11

user1905597


1 Answers

there are a few solutions, but depends on how much control you have on the server.

  1. If you have full access control to server, you may create a separate application which will take care of the Tasks; the application can be a Windows Service, and the communication between your page and the application would be either a database or MSMMQ (the communication mainly means the list of the Tasks and their states - 1. to be executed, 2. executing 3. finished).

  2. Another solution is in case you don't have full access control to server, but it will require to implement some communication between threads. Instead of having the application I described at point 1. you can have a separate thread, which can be started this way:

    System.Threading.ThreadPool.QueueUserWorkItem(foo => LauchTaskRunner());
    

    Suppose you implemented a method called LaunchTaskRunner which in a loop just processes the list of existing Tasks, the above line will start it into a separate process. You can communicate with this method (which is running in a separate thread) through some static variable (declared in the page), e.g.:

    public class YourPage : System.Web.UI.Page{
        static IList<Task> tasks;
        static void LauchTaskRunner(){
        // here make use of tasks variable
        }
    }
    

    Everytime the (tasks)updatepanel gets refreshed, it should render based on tasks variable.

like image 159
csg Avatar answered Nov 11 '22 16:11

csg