首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法处理ThreadAbortException

无法处理ThreadAbortException
EN

Stack Overflow用户
提问于 2014-05-06 22:16:29
回答 1查看 777关注 0票数 3

我有一个WCF服务,它接受请求,并为每个请求发出一个HTTPWebRequest调用并返回响应。我使用一个BlockingCollection来存储传入的请求,一个单独的线程处理(发出webrequest)集合中的项。有时,Webrequest会返回一个threadabortexception。我捕捉到它并执行一个Thread.ResetAbort。但是异常向上流动,它清除了BlockingCollection。我已经添加了下面的代码片段。我需要找到一种方法让foreach循环继续运行,即使我得到一个线程异常。

代码语言:javascript
复制
public static class YBProcessor
{
    static PriorityQueue<QueuePriorityLevel, string> queue = new PriorityQueue<QueuePriorityLevel, string>();
    static BlockingCollection<KeyValuePair<QueuePriorityLevel, string>> requests;
    static YBProcessor()
    {        
        requests = new BlockingCollection<KeyValuePair<QueuePriorityLevel, string>>(queue);
        Task.Factory.StartNew(() => SendRequestToYB());
    }
    public static void AddCalcRequest(string cusip, double price, QueuePriorityLevel priority)
    {
         requests.Add(new KeyValuePair<QueuePriorityLevel, string>(priority, cusip + "-" + price.ToString()));                                          
    }
   private static void SendRequestToYB()
   {
       // this is a separate thread that processes the requests as the come in.
      foreach (var obj in requests.GetConsumingEnumerable())
      {                 
          try
          {
            var request = GetXML(obj.Value);
            var response = YBClient.GetResponse(request);
            //code to handle response
          }
          catch (ThreadAbortException ex)
          {
            Thread.ResetAbort();
          }
          catch (Exception ex)
          {
          }
       }    
     }
}

//在YBClient中,GetResponse方法(只包含关键部分。代码无法编译)

代码语言:javascript
复制
private static String GetResponse(String text)
{
    for (iTry = 0; iTry < MAX_TRY; iTry++)
    {

        try
        {
            // Create and setup request
            bytes = encoding.GetBytes(text);
            request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = "POST";
            request.ContentType = "text/xml";
            request.ContentLength = bytes.Length;
            request.CookieContainer = cookieJar;
            request.Timeout = 100 * 1000;
            request.ReadWriteTimeout = 100 * 1000;

            // Prepare and send data
            postStream = request.GetRequestStream();
            postStream.Write(bytes, 0, bytes.Length);
            postStream.Close();

            // Get response from server
            response = (HttpWebResponse)request.GetResponse();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                reader = new StreamReader(response.GetResponseStream(), encoding);
                xmlResponse = reader.ReadToEnd();
                reader.Close();
                break;
            }               
            response.Close();
        }
        catch (ThreadAbortException ex)
        {
            Thread.ResetAbort();                
            break;              
        }           
        catch (Exception ex)
        {               
            if (ex.GetBaseException() is ThreadAbortException)
            {                   
                Thread.ResetAbort();
                break;
            }
        }
    }       
}
return xmlResponse;
}
EN

回答 1

Stack Overflow用户

发布于 2014-10-03 12:11:35

如果服务本身调用线程中止异常,那么这可能意味着服务正在关闭,在这种情况下,您的线程无法继续运行(想象一下应用程序池回收),如果您希望确保挂起的请求不会丢失,则可以执行以下操作之一:

1)启动一个新的appdomain http://msdn.microsoft.com/en-us/library/ms173139(v=vs.90).aspx

这种方法将缓解服务关闭,但仍然不能解决确保所有请求都得到处理的根本问题,因为“其他”应用程序域也可能会关闭。

2)更好的解决方案是在中央数据库或文件中以序列化的形式编写请求,并让工作人员不断从相同的数据库中弹出项目。如果你想简单,为每个请求创建单独的文件,并在处理后删除它们(假设你不会收到数千个请求/秒),对于更具可扩展性的解决方案,你可以使用Redis数据库(http://redis.io/)并使用它的“列表”(队列)功能。

附注:你可能想把你的线程(任务)标记为长时间运行,如果你不这样做,它会使用线程池,这对于长时间运行的任务是不推荐的。

代码语言:javascript
复制
 Task.Factory.StartNew(Run, TaskCreationOptions.LongRunning);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23497282

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档