C#SpinLock和线程。 StackOverflowException并退出代码259(0x103)

时间:2014-10-11 16:34:47

标签: c# multithreading stack-overflow spinlock

我对C#非常陌生,但这个项目的目标是让素数生成器使用线程锁定并使用多个处理核心。我以为我已经掌握了C#,但我遇到了一些问题。

在Visual Studio中运行会产生一堆:退出代码259(0x103)消息。 我已经读过这是Visual Studio的一个错误,实际上不是问题吗?

问题的核心是StackOverflowException。我熟悉堆栈溢出的概念,但是我无法确定堆栈溢出的位置。我可以猜测这与在某个地方填充我的队列有关。

计划如下:

Calculator.cs:从生成的文件中读取数字,将它们放入队列,在这些队列上开始线程

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace PrimeProject{
internal class Calculator {

    public void Run(NumberReader reader) {
        var results = new List<long>();
        var numbersToCheck = new Queue<long>();

        StartComputationThreads(results, numbersToCheck);

        var progressMonitor = new ProgressMonitor(results);

        new Thread(progressMonitor.Run) {IsBackground = true}.Start();

        var someList = new List<long>();
        foreach (var value in reader.ReadIntegers()) 
        {
            someList.Add(value);
            if (someList.Count == 1000)
            {
                numbersToCheck.EnqueueCollection(someList);
                someList.Clear();
            }
        }
        if (someList.Count > 0)
        {
            numbersToCheck.EnqueueCollection(someList);
            someList.Clear();
        }

        while (numbersToCheck.Count() > 0) 
        {
            Thread.Sleep(100); // wait for the computation to complete.
        }
        Console.WriteLine("{0} of the numbers were prime", progressMonitor.TotalCount);
    }

    private static void StartComputationThreads(List<long> results, Queue<long> numbersToCheck) 
    {
        var threads = CreateThreads(results, numbersToCheck);
        threads.ForEach(thread => thread.Start());
    }

    private static List<Thread> CreateThreads(List<long> results, Queue<long> numbersToCheck) 
    {

        var threadCount = Environment.ProcessorCount*2;

        Console.WriteLine("Using {0} compute threads and 1 I/O thread", threadCount);

        var threads =
            (from threadNumber in Sequence.Create(0, threadCount)
                let calculator = new IsNumberPrimeCalculator(results, numbersToCheck)
                let newThread =
                    new Thread(calculator.CheckIfNumbersArePrime) {
                        IsBackground = true,
                        Priority = ThreadPriority.BelowNormal
                    }
                select newThread).ToList();
        return threads;
    }
}
}

Semaphore.cs:自定义队列类,创建信号量,SpinLock调用。在尝试{}之前更新了bool lockTaken。

using System;
using System.Collections.Generic;
using System.Threading;

internal sealed class Queue<T>
{
private readonly Semaphore semaphoreOne;
private readonly Semaphore semaphoreTwo;
private readonly SpinLock _spinLock;
private readonly Queue<T> listQueue;

public Queue()
{
    this.semaphoreOne = new Semaphore(0x3e8, 0x3e8);
    this.semaphoreTwo = new Semaphore(0, 0x3e8);
    this._spinLock = new SpinLock();
    this.listQueue = new Queue<T>();
}

public int Count()
{
    int count;
    bool lockTaken = false;
    try
    {
        this._spinLock.Enter(ref lockTaken);
        count = this.listQueue.Count();
    }
    finally
    {
        this._spinLock.Exit();
    }
    return count;
}

public void EnqueueCollection(IReadOnlyCollection<long> collection)
{
    for (int i = 0; i < collection.Count; i++)
    {
        this.semaphoreOne.WaitOne();
    }
    bool lockTaken = false;
    try
    {
        this._spinLock.Enter(ref lockTaken);
        foreach (long local in collection)
        {
            this.listQueue.Enqueue(local);
        }
    }
    finally
    {
        this._spinLock.Exit(true);
    }
    this.semaphoreTwo.Release(collection.Count);
}

public void Enqueue(long num)
{
    this.semaphoreOne.WaitOne();
    bool lockTaken = false;
    try
    {
        this._spinLock.Enter(ref lockTaken);
        this.listQueue.Enqueue(num);
    }
    finally
    {
        this._spinLock.Exit();
    }
    this.semaphoreTwo.Release(1);
}

public long Dequeue()
{
    long local;
    this.semaphoreTwo.WaitOne();
    bool lockTaken = false;
    try
    {
        this._spinLock.Enter(ref lockTaken);
        local = this.listQueue.Dequeue();
    }
    finally
    {
        this._spinLock.Exit();
    }
    this.semaphoreOne.Release();
    return local;
}
}

SpinLock.cs:由于Semaphore.cs中的更改而被删除

其他类(供参考)包括:isNumberPrime,progressMonitor,reader和writer。

1 个答案:

答案 0 :(得分:1)

您的SpinLock类似乎有自己的实例,不确定您的意图是什么,但这导致无限创建SpinLock实例,它利用了所有堆栈内存,从而导致{{1 }}

我建议您为班级提供不同的名称,因为{B}已经采用了StackoverflowException