Reputation: 1271
Recently we've been getting System.Threading.ThreadAbortExceptions from an ASP.NET webservice that posts data to a payment server each night.
The webservice is a standard .asmx page that gets called from another client.
Inside the page I have a foreach loop that iterates through many payment rows in a database:
foreach (var obtRow in readyToBeCaptured)
{
try
{
status = dibs.GetPagePost(...);
// handle status here
}
catch (ThreadAbortException tex)
{
SingletonLogger.Instance.Error(string.Format("Transactionhandler - Could not Capture, Thread was aborted. {0}", tex.Message), tex);
}
catch (Exception ex)
{
SingletonLogger.Instance.Error(string.Format("Transactionhandler - Could not Capture, statuscode: {0}, message: {1}.", status, ex.Message), ex);
}
}
The strange thing is I get a log entry from catch(ThreadAbortException tex) block when this error occurs, but then the code breaks out and is caught in another try catch block further up the call tree. Ideally I would have the code inside the foreach loop to continue
This is the GetPagePost method
private bool GetPagePost(string url, NameValueCollection nameValueCollection, string userName, string password)
{
WebClient client = new WebClient();
if (userName != "")
{
client.Credentials = new NetworkCredential(userName, password);
}
foreach (string str in nameValueCollection.AllKeys)
{
this._callCollection.Add(str, nameValueCollection[str]);
}
StringBuilder builder = new StringBuilder();
builder.Append("DIBS.NET/1.2.0 ( ");
builder.Append("OS ").Append(Environment.OSVersion.Platform).Append(" ").Append(Environment.OSVersion.Version).Append("; ");
builder.Append(".NET CLR ").Append(Environment.Version).Append("; ");
builder.Append("User ").Append(Environment.UserName).Append("; ");
builder.Append("Domain ").Append(Environment.UserDomainName).Append("; ");
builder.Append(" ) ");
client.Headers.Add("User-Agent", builder.ToString());
try
{
byte[] bytes = client.UploadValues(url, "POST", nameValueCollection);
this._httpStatus = 200;
this._httpBody = Encoding.UTF8.GetString(bytes);
return true;
}
catch (WebException exception)
{
this._httpBody = exception.Message;
this._httpStatus = (int) exception.Status;
}
catch (UriFormatException exception2)
{
this._httpBody = exception2.Message;
this._httpStatus = -9999;
}
catch (Exception exception3)
{
this._httpBody = exception3.Message;
this._httpStatus = -99999;
}
return false;
}}
Why is this error occuring and how can I prevent the code from breaking out of the foreach loop? I've been looking at a few other posts here on StackOverflow but they seem to relate to the usage of Reponse.Redirect which I don't use.
Thanks
/Jens
Upvotes: 4
Views: 11378
Reputation: 2353
After some RND try few things:
httpRuntime targetFramework="4.5" maxRequestLength="4000" executionTimeout="45"
ref: http://dotnetvisio.blogspot.com/2013/07/solution-for-thread-being-aborted-call.html
Upvotes: 0
Reputation: 135
Last days I had a similar problem with a web service and solved it adding to </system.web>
of web.config this line: <httpRuntime executionTimeout="600"/>
.
600 is the number of seconds till is shut downed by asp.net. The default is 110 seconds.
It explains here better what it does.
Upvotes: 3
Reputation: 256
I have a similar issue. I think IIS is terminating your thread for taking too long. From your description "I have a foreach loop that iterates through many payment rows in a database", you may be able to restructure your app to process each row individually. Create a webmethod to send the rows to the client, then have the client iterate the transactions one at a time and process them in a different webmethod. Then you can handle exceptions that occur and keep going. You may even be able to process many at once using Parallel.ForEach
Upvotes: 4