Geeks With Blogs
Amit's Blog Sharing Thoughts and Learning

Asp.net 2.0 has a built-in feature for creating multi-threaded page AKA AsyncPage, but for Web Service threading, there are no out of the box support. The following code snippet will show you how to create a multi-threaded web service. For the sake of the example, let us assume that we are creating Video Search Service, which will search different sites such as YouTube, MetaCafe, and DailyMotion for a given keyword and returns a composite result. Since this search can be done independently, we can surly invoke separate threads for each search. Let us see how we can utilize the built-in ThreadPool to create a multithread web service.

    1 using System;

    2 using System.Threading;

    3 using System.Collections;

    4 using System.Collections.Generic;

    5 using System.Web;

    6 using System.Web.Services;

    7 

    8 

    9 public class Video

   10 {

   11     public string Title;

   12     public string Author;

   13     public string Description;

   14     public string Url;

   15     public string OriginalUrl;

   16     public string Thumbnail;

   17     public string Source;

   18 }

   19 

   20 [WebService(Namespace = "http://tempuri.org/")]

   21 [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

   22 public class VideoSearchService : WebService

   23 {

   24     public VideoSearchService()

   25     {

   26     }

   27 

   28     [WebMethod()]

   29     public List<Video> Search(string keyword)

   30     {

   36         List<Video> result = new List<Video>();

   37         List<ManualResetEvent> locks = locks = new List<ManualResetEvent>();

   38         ManualResetEvent evt;

   39 

   40         evt = new ManualResetEvent(false);

   41         locks.Add(evt);

   42         ThreadPool.QueueUserWorkItem(new WaitCallback(SearchDailyMotion), (object)(new object[] { keyword, result, evt}));

   43 

   44         evt = new ManualResetEvent(false);

   45         locks.Add(evt);

   46         ThreadPool.QueueUserWorkItem(new WaitCallback(SearchMetaCafe), (object)(new object[] { keyword, result, evt }));

   47 

   48         evt = new ManualResetEvent(false);

   49         locks.Add(evt);

   50         ThreadPool.QueueUserWorkItem(new WaitCallback(SearchYouTube), (object)(new object[] { keyword, result, evt }));

   51 

   52         //This will ensure that all the threads completes its search

   53         EventWaitHandle.WaitAll(locks.ToArray());

   54 

   55         return result;

   56     }

   57 

   58     private void SearchDailyMotion(object state)

   59     {

   60         object[] triplet = (object[])state;

   61 

   62         string keyword = (string)triplet[0];

   63         List<Video> result = (List<Video>)triplet[1];

   64         ManualResetEvent evt = (ManualResetEvent)triplet[2];

   65 

   66 

   67         //DailyMotion will searhed over here

   68 

   69         evt.Set(); // Search is complete, so notify the parent thread

   70     }

   71 

   72     private void SearchMetaCafe(object state)

   73     {

   74         object[] triplet = (object[])state;

   75         string keyword = (string)triplet[0];

   76         List<Video> result = (List<Video>)triplet[1];

   77         ManualResetEvent evt = (ManualResetEvent)triplet[2];

   78 

   79         //MetaCafe will be searched over here

   80 

   81         evt.Set(); // Search is complete, so notify the parent thread

   82     }

   83 

   84     private void SearchYouTube(object state)

   85     {

   86         object[] triplet = (object[])state;

   87         string keyword = (string)triplet[0];

   88         List<Video> result = (List<Video>)triplet[1];

   89         ManualResetEvent evt = (ManualResetEvent)triplet[2];

   90 

   91         // YouTube will be searched over here

   92 

   93         evt.Set(); // Search is complete, so notify the parent thread

   94     }

   95 }

 

The whole thing has been done in four steps:

 Step 1:

 We created few variables:

  • A Generic List of Video which holds the search result
  • A Generic List of Locks which is actually ManualResetEvent class
  • A ManualResetEvent class to instantiate for different search.

Step 2:

Starting each Search, this steps are repeated for the 3 different search:

  • We created an Instance ManualResetEvent class and Adds it in the locks list. ManualResetEvent is special class, which allows us to communicate with different threads by signaling.
  • Next, we queue a Task in a ThreadPool passing the Keyword, The Result list where the search result will be appended by the child thread and ManualResetEvent. The ThreadPool class method QueueUserWorkItem only takes a WaitCallback delegate which only accepts a single argument of object type and that's way we creating array on the fly and putting these items in that array. When a task is queued in the ThreadPool, the ThreadPool picks a free thread from its pool fires the thread to run the assigned method in that thread.

Step 3:

Inside the Child Thread :

  • Cast back the argument to proper types.
  • Search the Site. I have commnted this to make the code shorter
  • Then call the set() method of the ManualResetEvent. By calling this method, we are sending signal to the parent thread that the thread has done its job.

Step 4:

The parent thread:

  • The Parent threads call the EventWaitHandle.WaitAll(). This ensures that the parent thread will wait until all the child threads complete its job.

And We are Done!

Few Notes:

  • It is not possible to access the HttpContext.Current from the Child Thread method which means it also not possible to access the Request, Response, Cache, Session etc. If you need any of these objects in the child thread method then you also have to pass it in the WaitCallback like we did in the above.
  • Never Creates a New Thread alternatively use the Built in ThreadPool class.
  • Queuing a Task does not ensure that it will started be instantly, it completely depends upon the current usage of the ThreadPool, if the ThreadPool is already saturated with previous tasks then there might be a chance that your application will perform poorly even comparing with the Single threaded approach.

kick it on DotNetKicks.com

Posted on Tuesday, June 19, 2007 2:33 AM Asp.net , Tips/Tricks , Web Service , Threading | Back to top


Comments on this post: Utilize ThreadPool in WebService

# re: Utilize ThreadPool in WebService
Requesting Gravatar...
Nice article, thankyou for sharing :)
Maybe you could be interested to check at this article that's focused on the same argument, but on the opposite side
http://blog.madskristensen.dk/post.aspx?id=6b2ae805-21dc-4973-8d4d-96aec63c824c

Bye.
Left by NinjaCross on Jun 19, 2007 5:03 AM

# Link Listing - June 18, 2007
Requesting Gravatar...
Tip/Trick: Creating Packaged ASP.NET Setup Programs with VS 2005 [Via: ScottGu ] Calling an ASMX webservice...
Left by Christopher Steen on Jun 19, 2007 10:10 AM

# re: Utilize ThreadPool in WebService
Requesting Gravatar...
Checkout the http://msdn2.microsoft.com/en-us/library/ms998549.aspx#scalenetchapt06_topic8. I think it will help you to understand more on threading. Although it is recommened to avoid Multi-Threading in Asp.net application, especially creating new threads. But in certain condition we can use the async delegetes and threadpool but in that case the implementation must be well tested.
Left by Kazi Manzur Rashid on Jun 19, 2007 4:11 PM

Your comment:
 (will show your gravatar)
 


Copyright © Kazi Manzur Rashid | Powered by: GeeksWithBlogs.net | Join free