locked
TASK vs Thread on Asp.Net Web Form to improve perforrmance RRS feed

  • Question

  • User-1778011532 posted

    Dear All,

    In my ERP Web Application, User gives required input for the report in the web form and need not wait till the report is generated. A message would be shown to user as "Report is Generating". and user can see the generated report in other place on the same web application. 

    I have used asychronous ways of generating report using TASK instead of Thread as given below.

    clsRDL objRDL = new clsRDL();
    
    RDLReportDetails rdlReportDetails = new CLsRDLGeneratePDFReportDetails("/Report1",strOutputFileName,strUserName,strpwd,strDomainName);
    
    Task.Factory.StartNew(() => objRDL.GenerateReport(rdlReportDetails);

    Generate Report is a method which call SSRS report to generate report and save the same to specified location.

    Everything work fine. My concern is how do I know TASK is better option over thread which uses Thread pool to improve performance and better garpage collection.

    Since for each report and each request, it create one task and that cycle is over since it is web application. How subsequent request would use thread reated by earlier request.

    Do I need to modify the followig code to use  thread pool?  I was monitoring the perfmon to see garpage collection, I couldn't see any difference between TASK and THREAD.

    Task.Factory.StartNew(() => objRDL.GenerateReport(rdlReportDetails);

    Kindly suggest.

    In addition whether to keep this Generatereport Method as Static Method / In a Singleton class / Normal class which better memory management option.

    if it is Static then I need to lock the method from start to end to avoid concurrent problem since all report call the same method.

    Please suggest the better approach.

    WIth Regards

    Palanivelrajan

    Tuesday, March 25, 2014 11:46 AM

Answers

  • User-760709272 posted

    The thing about a Windows Service is that it is always running so you have to know how to deal with the occassions when nothing is happening as you can't write code like

    do
    {
       if (workNeedsDone)
       {
           doWork();
       }
    } while (true);

    as it hammers resources.  The advantage of using msmq is that you can get your code to just wait until something comes on the queue.  So your code is sleeping and "wakes up" when something hits the queue.  If you wanted to poll a database then you'd need to handle your own sleep management.  The most basic way of doing this is

    while (running)
    {
        DoWork();
        Thread.Sleep(5000);
    }

    That will check if anything needs done and then just wait for 5000s so your service only "wakes up" briefly once every 5 seconds.  Writing services it outside the scope of this forum but there are better ways than Sleep such as the AutoResetEvent.  When you're writing a service that sleeps you have to remember that your code needs to be able to react to a Stop or Restart command from the service manager.  So most services kick of a work thread on a new thread so that the original thread can respond to a Stop.  Then the work thread ususes AutoResetEvent so the original thread can wake it up when a Stop command comes in.  If you google for writing windows services you'll find this kind of code fiarly easily.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, March 29, 2014 7:59 AM

All replies

  • User-1423995609 posted

    Let's begin with the title of your question

    Task vs Thread on ASP.NET Web Form to improve performance

    Task or in that matter using thread won't be giving you any performance gain. They are all about "doing some stuff" in parallel. So for example if you have some "stuff to do" that can actually be divided into smaller pieces, and processed in parallel, then you might improve performance. In your case, your task is to generate a report, and it is a simple method call, so from what I see there is nothing that can be divided to sub-tasks and processed in parallel. So actually code that you have won't be giving you any performance improvements.

    Your question is little bit confusing, in the title you're reffering to Task vs Thread, than in the question your asking whether you should switch to ThreadPool. If you create a Thread, you'll be creating actual OS-level thread with it's own resources, which is costly, as it will have it's own memory for it's stack, additional CPU cycles because of processor's context-switches. This is something I would highly recommend you to stay away from.

    If we're talking about Queueing some user work on ThreadPool or using Task, mostly it will be the same (as you're stating in the post, you couldn't see any difference between Task and using ThreadPool). The reason is that TPL's default Scheduler will use ThreadPool's threads to perform tasks on them, and since you're using the default one, there is no difference in regards of resources being used.

    Now IIS uses Thread Pool's threads to serve requests, so if you fire too much of tasks (or queue work on ThreadPool), you will actually consume some of those threads that are dedicated to serve the requests. Keep in mind also, that IIS actually restarts AppDomain periodically, so running a task is not safe in terms that, while task will run, IIS recycling may occur, and your task will be terminated without finishing.

    So putting this all together, your code is not improving anything, but actually consumes some threads from the threadpool, and has potential danger, that it won't be finished (in case of IIS recycling).

    Going further, you said that users don't have to wait until report is generated, they will be notified when it's done, and they will check the report later, on a different page, so it's hard to understand what kind of performance improvement you're seeking here?

    Remember, in general, async calls don't give you performance gain, they give you scalability gain - by processing long-running tasks on different thread (other than Thread Pool thread), which let's current thread to get back to Thread Pool to serve other requests. 

    What I would do in this case, I would have some web service, that is responsible to fire report generation, and have that web service called asynchronously from the client (using javascript or jQuery), and once it's done I would notify user (again this won't give any performance improvement, it will simply keep page alive, and user can continue working on the page).

    Tuesday, March 25, 2014 7:53 PM
  • User-1778011532 posted

    Dear Manvel,

    Thanks for spending your valuable time on this.

    My intend is keeping the page alive that is user need not wait till report is generated and he can perfom some other task on the web application. It will not notify report is completed instead "Report is being generated" message thrown immediately once taks is started . if user want to see the status, it will be shown to user in another place based on the status I insert into table for tracking the progress(ie. before generating the report one record is inserted and after completion status is updated for that record). In this context I am using TASK instead of thread, I would like to see whether TASK is using threadpool through Perfmon tool. My concern is How asp.net will keep thread pool based on TASK object(since i am not giving any name to it) and each request is one cycle and how subsequent requet use earleir one.

    JQUERY AJAX Web Service is a good Idea but user need to wait till the AJAX call completes(that is after report is generated) but  I want user to perform some other task(Either on the same screen or different screen) after giving input to generate report and need not wait till report is generated.

    Please guide me on this

    Thanks and Regards

    Palanivelrajan

    Tuesday, March 25, 2014 10:23 PM
  • User-1423995609 posted

    Then the best option for you is to use "fire and forget" approach. Implement Web Service, that will have one way operation contract defined. This Operation contract, will be responsible to fire report generation. It does exactly the same thing you want - client (either from js, or from server side) will make a call to a service, service will get the call, and immediately return. Think of it as - client notifies service to do some stuff, service replies "I got it, I'm on it", so you know that report is being generated, and you can notify your user.

    As I said, Task or Thread will consume thread pool's thread to do this stuff, which is not the best option. In terms of how subsequent requests will use the same thread - it doesn't really matter, anyway thread from threadpool will be busy doing this stuff.

    However, if you don't have too many users, and subsequently report generation is not triggered too often, then I would not add complexity to application (by implementing one-way service etc...). You're wrong that if you use jQuery AJAX calls, user has to wait for reply, since it's an AJAX call, it will be done in the bacground, so user will continue working on the page. Of course you can subscribe to success callback for AJAX call, but since you are not interested in progress, nor whether report generation was successful or not, you can simply make it work.

    Wednesday, March 26, 2014 5:05 AM
  • User-760709272 posted

    In terms of performance, if one gives an improvement over abother it will be measured in milliseconds which is irrelevant given the vast majority of your task is taken up generating the report.  In general asp.net is not the best technology to process long-running tasks for reasons already stated.  If possible, what I would do is create a windows service that monitors a queue (database, MSMQ, folder on the drive, whatever) and all your asp.net code does is write to that queue giving the parameters for the report and the service picks this up and does the processing.  If you use something like a database to store the queue, your service can mark that the job is done and your asp.net code can look at the queue to see the job is done and retrieve the report from wherever the service writes it to.

    Wednesday, March 26, 2014 5:41 AM
  • User-1778011532 posted

    Dear Manvel,

    Thanks for your valuable suggestion. let me look into this. 

    Thanks and Regards

    Palanivelrajan

    Saturday, March 29, 2014 12:51 AM
  • User-1778011532 posted

    Dear AidyF,

    Thanks for sharing your valuable suggestion. I had used Windows Service and MSMQ in my earlier ERP Web Application but it was getting stopped abrubtly when it was on testing so we removed windows service and MSMQ. Web Application would write the request into MSMQ and Windows service read it from MSMQ and call Business layer which inturn interact with DB. 

    Application concurrent user is 1000+ with load balancer.

    You have suggested Windows service that monitor the queue (database, MSMQ, folder on the drive, whatever).  

    May I know, whether windows service uses timer control to monitor the msmq/ db/ folder in an interval or any other better. if I use db do need to query the specific table in interval or any other approach for notifying request.

    Please suggest me the best approach as well as pro and cons of each to monitor the database, MSMQ, folder on the drive, whatever.

    Thanks and Regards

    Palanivelrajan

    Saturday, March 29, 2014 1:04 AM
  • User-760709272 posted

    The thing about a Windows Service is that it is always running so you have to know how to deal with the occassions when nothing is happening as you can't write code like

    do
    {
       if (workNeedsDone)
       {
           doWork();
       }
    } while (true);

    as it hammers resources.  The advantage of using msmq is that you can get your code to just wait until something comes on the queue.  So your code is sleeping and "wakes up" when something hits the queue.  If you wanted to poll a database then you'd need to handle your own sleep management.  The most basic way of doing this is

    while (running)
    {
        DoWork();
        Thread.Sleep(5000);
    }

    That will check if anything needs done and then just wait for 5000s so your service only "wakes up" briefly once every 5 seconds.  Writing services it outside the scope of this forum but there are better ways than Sleep such as the AutoResetEvent.  When you're writing a service that sleeps you have to remember that your code needs to be able to react to a Stop or Restart command from the service manager.  So most services kick of a work thread on a new thread so that the original thread can respond to a Stop.  Then the work thread ususes AutoResetEvent so the original thread can wake it up when a Stop command comes in.  If you google for writing windows services you'll find this kind of code fiarly easily.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, March 29, 2014 7:59 AM
  • User-1778011532 posted

    Dear _Manvel,

    I found that 

    If the client issues a one-way call and then closes the proxy while the method executes, the client will still be blocked until the operation completes. but I don't want my client to be blocked once proxy is closed. I didnot implmented this but I found that client is blocked in the following URL.

    http://www.c-sharpcorner.com/UploadFile/4d56e1/one-way-operations-in-wcf-services/

    Thaanks and Regrads

    Palanivelrajan
     

    Tuesday, April 15, 2014 12:27 AM
  • User-1423995609 posted

    Well first of all, do not trust everything you see in internet. If it is in internet, it doesn't mean it is true!

    I checked the post, you misunderstood the point author was trying to make.

    Once again, One-way WCF calls are not blocking until execution completes, merely it is returning to the client once request is accepted by service.

    And finally, you could just check it yourself, whether it is true statement or not.

    Create 2 projects in Visual Studio - Console Application (this will be client), and WCF service application (this will be service we're going to call).

    Define just one method on your WCF service, it should look like this

    [ServiceContract]
    public interface IService1
    {
        [OperationContract(IsOneWay = true)]
        void DoSomeWork();
    }

    And here's the implementation

    public class Service1 : IService1
        {
            public void DoSomeWork()
            {
                Thread.Sleep(10000);
            }
        }

    As you can see I'm calling thread.sleep, which should imitate long time execution that lasts 10 seconds. We're going to call this method from the client, and if one-way service calls are blocking unless execution completes, we should wait abt 10 seconds (in other words our client should block for 10 seconds).

    Here's the Console application's Main method. As you can see it makes a call to one way method, records time it took to return from the call, and outputs on the console.

    static void Main(string[] args)
            {
                Console.WriteLine("About to call one way WCF method.");
                Console.WriteLine("Method call should immediately return.");
                Console.WriteLine("Time client was blocked will be captured and printed to console.");
                Console.WriteLine("Press any key to make a call.");
                Console.ReadLine();
    
                Stopwatch stopwatch = new Stopwatch();
                using (var client = new OneWay.Service1Client())
                {
                    stopwatch.Start();
                    client.DoSomeWork();
                    stopwatch.Stop();
                }
    
                Console.WriteLine("Time took to call client {0} ms", stopwatch.ElapsedMilliseconds);
                Console.WriteLine("Press any key to exit the program.");
            }

    If you run it, you will see that it is not taking even 1 second to return from the call.

    Tuesday, April 29, 2014 1:06 PM