线程正在中止 - 使用队列C#

时间:2014-04-10 06:27:38

标签: c# queue box-api

我们已经实现了一个队列,用于将文件上传到box.net。 所有文件都已成功上传。但是,我在一周内得到以下例外1或2次。我无法找到导致此异常的任何原因。

异常消息:

  

线程正在中止。

异常-来源:

  

mscorlib程序

异常堆栈跟踪:

  

at System.Threading.Monitor.ObjWait(Boolean exitContext,Int32 millisecondsTimeout,Object obj)   在System.Threading.Monitor.Wait(Object obj,Int32 millisecondsTimeout,Boolean exitContext)   在System.Threading.Monitor.Wait(Object obj)   at Box.netAPIWebApp.Service.BoxService.monitorOnUploadQueue()在C:\ Project \ BackupProjects \ BoxNetFileUpload \ Box.netAPIWebApp \ Source \ Service \ BoxService.cs:第90行

任何人都可以帮忙吗?

private static readonly BoxService instance = new BoxService();

private Queue<FileCabinetUploadHistory> uploadQueue = new Queue<FileCabinetUploadHistory>();


private BoxService()
{
    Thread monitorThread = new Thread(new ThreadStart(monitorOnUploadQueue));
    monitorThread.Start();
}

private FileCabinetUploadHistory RemoveFromUploadQueue()
{
    lock (uploadQueue)
    {
        return uploadQueue.Dequeue();
    }
}

private void monitorOnUploadQueue()
{
    FileCabinetUploadHistory fileCabinetUploadHistory = null;
    try
    {
        while (true)
        {
            if (uploadQueue.Count < 1)
            {
                lock (uploadQueue)
                {
                    Monitor.Wait(uploadQueue);
                }
            }
            fileCabinetUploadHistory = uploadQueue.Peek();

            if (fileCabinetUploadHistory != null)
            {
                StartFileUpload(fileCabinetUploadHistory);
            }
        }
    }
    catch (Exception exception)
    {
        log.Error("Error:--> Class name: BoxService, Method name: monitorOnUploadQueue() \n", exception);
    }
}

public void AddToUploadQueue(FileCabinetUploadHistory fileCabinetUploadHistory)
{
    lock (uploadQueue)
    {
        if (!uploadQueue.Contains(fileCabinetUploadHistory))
        {
            uploadQueue.Enqueue(fileCabinetUploadHistory);
            Monitor.Pulse(uploadQueue);
        }
    }

}     

2 个答案:

答案 0 :(得分:6)

基本上ThreadAbortException意味着:你的线程收到一个外部信号来自杀。现在ThreadAbortException有点特殊,因为它无法处理。它只是通过每次捕获它时重新抛出自己来继续终止你的线程。有关详细信息,请参阅http://ericlippert.com/2009/03/06/locks-and-exceptions-do-not-mix/

所以现在你可能会问自己是谁发送了上面提到的外部信号。我不知道。你展示的代码不足以说明。但是很有可能某人仍然拥有monitorThread的句柄并且在其上调用thread.Abort()。您的代码库是否包含.Abort()?如果是这样,请放心,这是一个非常糟糕的主意。有关详细信息,请再次参阅上述链接。

如果你必须终止正在监视器上等待的线程,那么有更好的方法。例如,让线程同时在多个监视器上等待:一个用于队列,另一个用于终止信号。然后不是通过中止来杀死线程,而是让脉冲终止监视器并让线程自行关闭。

顺便说一句,您是以不安全的方式访问您的队列。写访问似乎处于锁定状态,但读访问(Count,Peek)不是。这不是锁定应该被使用的方式,坏的事情可能(并且最终会发生)。不要这样做!请参阅http://blog.coverity.com/2014/03/12/can-skip-lock-reading-integer/以了解原因。

答案 1 :(得分:3)

我明白了。 应用程序池每29小时后回收一次,就会发生ThreadAbortException。