Click here to Skip to main content
15,887,485 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I have developed an ASP.NET (.asmx) webservice in C#. Just before it returns, it starts a thread (have tried via the threadpool and a simple thread) to perform a web request. Before creating the web request, I need a delay of about 1 - 2 seconds. I have tried a Sleep, a Timer, and even a for loop counting into the millions. On my development server (Server 2012 R2) it works all of the time. On the customer's server thousands of miles away in a different country, but also on Server 2012 R2, it works less than 10% of the time. According to my logging, the thread ends sometime during the delay, before the web request. What could be killing it? Does ASP.NET decide it is not active?

Code:



I have developed an ASP.NET (.asmx) webservice in C#. Just before it returns, it starts a thread to perform a web request. Before creating the web request, I need a delay of about 2 seconds. I have tried a Sleep, a Timer, and even a for loop counting into the millions. On my development server it works all of the time. On the customer's server, it works less than 10% of the time. According to my logging, the thread ends sometime during the delay, before the web request. What could be killing it? Does ASP.NET decide it is not active?
It logs "TesterRequest: Before WAIT of" then the System exception "Thread was being aborted" (see code below), then of course nothing else.
Relevant Code - Below is the for loop version (put in the for loop just to test after sleep and timer methods failed to be sustained, were aborted before elapsed time was completed): 

static void ThreadProc(object p_tcti)
{

        // Calls a method inside the tester via HttpWebRequest

            int nSleep = 606111000; // 2000;
            LogMessage(DateTime.Now.ToString() + " ms: " + DateTime.Now.Millisecond.ToString() + ". " + "TesterRequest: Before WAIT of " + nSleep.ToString());

            int nDummy = 0;
            for (int n = 0; n < nSleep; n++)
            {
                nDummy = n;
            }

            LogMessage(DateTime.Now.ToString() + " ms: " + DateTime.Now.Millisecond.ToString() + ". " + "TesterRequest: After WAIT " + nDummy.ToString() + " creating web request to tester.");
            HttpWebRequest reqWeb = (HttpWebRequest)WebRequest.Create(tcti.m_strURL);
            LogMessage(DateTime.Now.ToString() + " ms: " + DateTime.Now.Millisecond.ToString() + ". " + "TesterRequest: Created the web request.");
            reqWeb.Method = "GET";
            //reqWeb.MaximumAutomaticRedirections = 4;
            //reqWeb.MaximumResponseHeadersLength = 4;
            reqWeb.UserAgent = "ABRWebService /1.0";
            // Do it!  This will block for up to 40 seconds
            string strStatus = "";
            reqWeb.Timeout = 40000;
     try
     {
                HttpWebResponse resWeb = (HttpWebResponse)reqWeb.GetResponse();
                //       LogMessage(DateTime.Now.ToString() + " ms: " + DateTime.Now.Millisecond.ToString() + ". " + "TesterRequest: Received response from the tester web request. ");
                if (resWeb.StatusCode != HttpStatusCode.OK)
                {
                    strStatus = resWeb.StatusDescription;
                    LogMessage(DateTime.Now.ToString() + " ms: " + DateTime.Now.Millisecond.ToString() + ". " + "TesterRequest FAILED" + " " + strStatus);
                }
                resWeb.Close();
            }
            catch (WebException we)
            {
                // Ignore timeouts since we don't give a about the
                // response.
                tcti.m_strResult = we.Message;
                if (we.Status != WebExceptionStatus.Timeout)
                {
                    LogMessage(DateTime.Now.ToString() + " ms: " + DateTime.Now.Millisecond.ToString() + ". " + "TesterRequest Web Exception:  " + we.Message + "  Request:  " +
                    tcti.m_strResult + ", URL:  " + tcti.m_strURL);
                    if (!strStatus.Equals(""))
                        LogMessage("Status: " + strStatus);
                    LogMessage("TesterRequest FAILED" + " " + DateTime.Now);
                    // RWC don't throwthrow we;
                }
            }
            catch (Exception ex)
            {
                LogMessage(DateTime.Now.ToString() + " ms: " + DateTime.Now.Millisecond.ToString() + ". " + "TesterRequest Exception:  " + ex.Message);
            }

            LogMessage(DateTime.Now.ToString() + " ms: " + DateTime.Now.Millisecond.ToString() + ". " + "TesterRequest Succeeded.");

}

public TesterRequest(string p_strURL)
{       {
  try
  {
                TesterCommThreadInfo tcti = new TesterCommThreadInfo();
                tcti.m_strURL = p_strURL;
                   LogMessage(DateTime.Now.ToString() + " ms: " + DateTime.Now.Millisecond.ToString() + ". " + "TesterRequest: Begin queueing a thread to trigger program download.");
                   ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc), tcti);
               // Service.LogMessage(DateTime.Now.ToString() + " ms: " + DateTime.Now.Millisecond.ToString() + ". " + "TesterRequest: Begin - Create and launch a new thread to trigger program download.");
                // 6/4/18 changed to simple thread from thread pool for better reliability.
                //Thread tr = new Thread(() => ThreadProc(tcti));
                //tr.Start();
                //Service.LogMessage(DateTime.Now.ToString() + " ms: " + DateTime.Now.Millisecond.ToString() + ". " + "TesterRequest: End - Create and launch a new thread to trigger program download.");
                   LogMessage(DateTime.Now.ToString() + " ms: " + DateTime.Now.Millisecond.ToString() + ". " + "TesterRequest: End queued a thread to trigger program download.");
            }
            catch (ThreadAbortException tae)
            {
                Service.LogMessage(DateTime.Now.ToString() + " ms: " + DateTime.Now.Millisecond.ToString() + ". " + "TesterRequest Thread Abort Exception Creating and/or launching new thread for program download: " + tae.Message);
            }
            catch (AppDomainUnloadedException aue)
            {
                Service.LogMessage(DateTime.Now.ToString() + " ms: " + DateTime.Now.Millisecond.ToString() + ". " + "TesterRequest App Domain Unloaded Exception Creating and/or launching new thread for program download: " + aue.Message);
            }
            catch (Exception ex)
            {
                Service.LogMessage(DateTime.Now.ToString() + " ms: " + DateTime.Now.Millisecond.ToString() + ". " + "TesterRequest Exception Creating and/or launching new thread for program download: " + ex.Message);
            }
        }
    }
}

What I have tried:

Tried changing from threadpool thread to simple thread. Tried three different delays. First delay was a System Threading Thread Sleep. Then I attempted a System Timer. Finally, in a strong attempt to eliminate the appearance my thread was inactive, I used a for loop counting into the millions for the dealy.
Posted
Updated 18-Jun-18 4:39am

1 solution

Your ASP.NET code is only running for the time it takes to fulfill the incoming request. If you "fire and forget" a thread, that thread is going to be terminated once ASP.NET returns a response to the client.

Your code has to wait for the thread to finish its work before returning anything to the client.
 
Share this answer
 
Comments
uniqman 18-Jun-18 15:40pm    
Thanks for your response. But can you explain how it works 100% of the time on my Server 2012 R2 and 10%-50% of the time on customers' same? We were able to go from 10% to 50% by shrinking the delay from 2 seconds to about 600ms.
uniqman 18-Jun-18 15:42pm    
Also, I neglected to mention in the original posting that this thread-spawning code and the thread code itself were borrowed from a web application that has always worked well to send files to our test equipment.
Dave Kreskowiak 18-Jun-18 16:19pm    
Nope, because I no absolutely nothing about your code. I only gave you a "for example" to think about.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900