locked
Humbly ask for straight answer regarding thread safety of ihttphandlers RRS feed

  • Question

  • User1523000192 posted

    Hi,

        I have a silverlight app that allows for the viewing and annotation of pdfs in an ink presenter. Once the annotation is done, the bitmap is passed to an ihttphandler in the hosting web project to be converted back into pdf format which is eventually saved to a field in a sql server database.

        I had gotten this working perfectly but when I tried to send multiple bitmapped pdfs to the ihttphandler through multiple calls I found that only one of the pdfs was being saved. Though I am passing different IDs for the images to each call, the context stream is the same for all calls to the handler. In other words, despite the fact that the calls are passing different bitmaps for different pdfs and also passing different IDs to save the different pdfs to the database, only one of the bitmapped pdfs is being saved to all the ID's. Obviously the context stream is the same for all calls to the ihttphander and the same pdf is being passed despite the fact that the calls to the handler pass different pdfs.

       I hope that isn't too confusing. I have posted a similar question before and have?

    gotten few responses that discusss theoretically, the use of IsReusable. However I haven't gotten any responses that specifically address the issue of my wanting the "right" pdf to go to the right call to the handler. Unfortunately this is not a technology I'm familiar with and I ask respectfully that some of my questions be answered:

       1.  Is the ihttphander able to process seperate calls and process the stream sent to it in the request. I have set IsReusable to false and still gotten the same result: all of the pdfs were overwritten by one of the pdfs passed to the various calls to the handler.

       2. Do I need to use an ihttpAsynchandler to make the get the desired result.

       3. Is there some other technique I need to use to make the calls to the ihttphander "thread safe", meaning that I want the pdf bitmap I am passing?

       I have also investigated using wcf but found that there are special considerations for services that take streams (you can only pass one parameter, the stream, unless you use message contracts to put the other parameters. This is also not something I'm familiar with. I'm looking for the easiest alternative.

       Thanks for listening. I had thought that setting IsREsueable to false would solve my problem but it didn't work.

    Fig000

    Saturday, July 23, 2011 7:08 PM

All replies

  • User423092291 posted

    First of all, a couple of words about HttpHandlers. The ASP.Net infrastructure has some kind of pool of your HttpHandler-objects. If a request come and the pool is empty, the ASP.Net creates a new instance of your HttpHandler. When this HttpHandler-object finish working and if its IsReuseble=true, the ASP.Net will put this HttpHandler-object to the pool for one of the next requests. If IsReusable=false, HttpHandler-object will be just destroyed.
    In one time HttpHandler-object processes only one request, the same instance can't be executed for another request in parallel.

    If IsReuseble=true and if you added any custom properties/fields to your HttpHandler, theoretically, you can have some arbitrary problems, when the values of properties/fields corresponds to previous request, which the instance was used for before. If IsReuseble=false, a new instance of your HttpHandler will be created for each request.

    I think you have some problems in your HttpHandler, it will be great if you post your code here to solve your problem with HttpHandlers.

    Thanks!

    Saturday, July 23, 2011 9:41 PM
  • User1523000192 posted

    Net Follower

    Thanks so much for answering. I really am working in the dark here and need to find some way of resolving this.

    I've read what you discuss regarding IsREsuable in other posts but I'm confused by it. I understand that using one handler speeds things up but I don't know how that affects my problem: should makeing IsResuable false force three handers to be created AND make the right bitmap go to the right handler based on the call.

    Here is my code with the conversion to pdf part removed for clarity. The point is the I make, say, three calls in which I pass one bit map to the handers along with ImageID for the image in a querystring parameter. Each call to the handler will have a bitmap and an ImageID.

    I was hoping that setting IsReusable to false would force the right bitmap and imageid to go to the right handler since (I think) that it would cause a new handler to be created for each call. That didn't work. What is happening regardless of whehter IsResuable is true or false is that all three calls seem to have the same stream (e.g. the same pdf bitmap).

    Oddly I put a break point in the handler. The imageid does change but the context stream doesn't. Let's say again that I have three seperate pdfs and each one is sent to a "new" handler by setting IsResusable to false. What happens when I check the three imageids in the database I find that all three image fields have the same pdf. Oddly one of the three database fields has a clear version of the pdf. The other two have a sort of "corrupted" version of the same pdf; there are smudges and odd lines.

    Below is the code from my handler. The returneed bytes in the response are irrelevant; I put them there as a place holder and a way to check twhat is sent back from the handler. Let me know if there are any questions. I appreciate the help.

    -------------------------------------------

    <%@ WebHandler Language="C#" class="Png2Pdf" %>

    using System;
    using System.Web;
    using iTextSharp.text;
    using iTextSharp.text.pdf;
    using System.Data.SqlClient;
    using System.Drawing;
    using System.Text;
    using System.IO;

     

    /// <summary>
    /// Summary description for Png2Pdf
    /// </summary>
    public class Png2Pdf : IHttpHandler
    {
        private int _BufferSize = 32768;
        private int _Margin = 54; // 3/4 inch margin
        private int startPagePosition = 0;
        private int endPagePosition;
        private byte[] inputStreamArray;
        private byte[] onePage;
        private object temponePage;
        private double aspectRatio;
        private System.IO.MemoryStream temp;

        public void ProcessRequest(HttpContext context)
        {
            if (context.Request.ContentLength <= 0)
                return;

             System.IO.Stream incomingStream = context.Request.InputStream;  //Get the incoming stream
             inputStreamArray = new byte[incomingStream.Length];
             incomingStream.Read(inputStreamArray, 0,(int) incomingStream.Length);

             System.IO.MemoryStream pdfStream = new System.IO.MemoryStream();
           
           
             //IRRELEVANT CODE REMOVED! THIS IS WHERE THE INCOMING STREAM (A BIT MAP OF ONE OR PDF PAGES) IS CONVERTED BACK TO PDF FORMAT AND STORED IN PDFSTREAM.

             //Stream the exported pdf to the client this is needed since the file size could be large in size
             Byte[] bytesRead = new Byte[pdfStream.Length];

             long toRead = pdfStream.Length; //Var used to determine how much to read
             pdfStream.Read(bytesRead, 0, (int)pdfStream.Length);

             try
             {
                 SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["CN_eLogWeb"].ConnectionString.ToString());
                 string sql = "Update Image set Image = @eimg where ImageID=" + Convert.ToString(context.Request.QueryString["ImageID"]);
                 SqlCommand cmd = new SqlCommand(sql, con);
                 con.Open();
                 cmd.Parameters.AddWithValue("@eimg", bytesRead);
                 cmd.ExecuteNonQuery();
             }
            catch (Exception Ex)
            {
                     throw new Exception(Ex.Message);
            }   
                
      
             context.Response.OutputStream.Flush();
             context.Response.Clear();
             context.Response.ContentType = "text/plain";
             context.Response.Write("Hello World");
             context.Response.Buffer = false;

             //Close and displose of the memory stream
             if (pdfStream != null)
             {
                 //pdfStream.Close();
                 // pdfStream.Dispose();
                    
               
             }
           
        }
       
       

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }

    --------------------------------------------

     

    Sunday, July 24, 2011 12:11 AM