lock free BulkCollector and FatalExecutionEngineError except

本文关键字:FatalExecutionEngineError except and BulkCollector free lock | 更新日期: 2023-09-27 18:19:03

我正在研究一个无锁的堆栈和队列数据结构,在那里我可以放置尽可能多的添加项,并在一次调用中收集所有项,我认为我的设计是可靠的,它按预期工作,直到我开始收到一个意外的异常,我认为这在纯c#环境中是不可能的:

托管调试助手'FatalExecutionEngineError'已检测到一个问题。附加信息:运行时遇到致命错误。错误的地址是0x6caf6ac7,在线程0x16f0上。错误码为0xc0000005。此错误可能是CLR中的错误,也可能是用户代码中不安全或不可验证部分中的错误。此错误的常见来源包括COM-interop或PInvoke的用户封送错误,这可能会损坏堆栈。

我似乎无法找到它发生的方式,想知道是否有人可以告诉我错误的原因:

这是stackbulkcollector的实现:

public class StackBulkCollector<T> : IBulkCollector<T>
{        
    class Node
    {
        public T value;
        private bool m_isSet;
        private Node m_prev;
        public Node(T data)
        {
            value = data;
        }
        public Node()
        {                
        }
        public Node Prev
        {
            set
            {
                m_prev = value;
                m_isSet = true;
            }
            get
            {
                if (!m_isSet)
                {
                    SpinWait s = new SpinWait();
                    while (!m_isSet)
                    {
                        s.SpinOnce();
                    }
                }
                return m_prev;
            }
        }
    }
    class Enumerable : IEnumerable<T>
    {
        private Node m_last;
        public Enumerable(Node last)
        {
            m_last = last;
        }
        public IEnumerator<T> GetEnumerator()
        {
            return new Enumerator(m_last);
        }
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return new Enumerator(m_last);
        }
    }
    class Enumerator : IEnumerator<T>
    {
        private readonly Node m_last;
        private Node m_current;
        public Enumerator(Node last)
        {
            var node = new Node();
            m_current = m_last = node;
            node.Prev = last;
        }
        public T Current
        {
            get { return m_current.value; }
        }
        public void Dispose()
        {
        }
        object System.Collections.IEnumerator.Current
        {
            get { return this; }
        }
        public bool MoveNext()
        {
            if (m_current == null)
            {
                return false;
            }
            m_current = m_current.Prev;
            return m_current != null;
        }
        public void Reset()
        {
            m_current = m_last;
        }
    }
    private Node m_last;
    public void Add(T data)
    {
        var node = new Node(data);
        node.Prev = Interlocked.Exchange(ref m_last, node);
    }
    public IEnumerable<T> GetBulk()
    {
        var last = Interlocked.Exchange(ref m_last, null);
        return new Enumerable(last);
    }
}

这是我用来测试它的测试程序:

class Program
{
    public static readonly int UseThreads = 4;
    public static readonly TimeSpan Duration = new TimeSpan(0,0,0,3);
    public static long[] AddedItems = new long[UseThreads];
    static void Main(string[] args)
    {
        IBulkCollector<TestData> bulkCollector = new QueuedBulkCollector<TestData>();
        while (true)
        {
            using (var countdownEvent = new CountdownEvent(UseThreads + 1))
            {
                var results = new Dictionary<int, List<TestData>>();
                if (bulkCollector is QueuedBulkCollector<TestData>)
                {
                    bulkCollector = new StackBulkCollector<TestData>();
                    Console.WriteLine("Starting StackBulkCollector Test");
                }
                else
                {
                    bulkCollector = new StackBulkCollector<TestData>();
                    Console.WriteLine("Starting QueuedBulkCollector Test");
                }
                for (int i = 0; i < UseThreads; i++)
                {
                    results[i] = new List<TestData>();
                    Thread t = new Thread(PushTestData);
                    t.Start(new object[] {i, bulkCollector, countdownEvent});
                }
                var start = DateTime.Now;
                Thread readerThred = new Thread(() =>
                                                    {
                                                        while ((DateTime.Now - start) <
                                                               (Duration - new TimeSpan(0, 0, 0, 0, 100)))
                                                        {
                                                            foreach (var testData in bulkCollector.GetBulk())
                                                            {
                                                                results[testData.Id].Add(testData);
                                                            }
                                                            //Console.WriteLine("Doing Some Read {0}", currBulk.Count);
                                                            System.Threading.Thread.Sleep(10);
                                                        }
                                                        countdownEvent.Signal();
                                                    });
                readerThred.Start();
                countdownEvent.Wait();
                var lastBulk = bulkCollector.GetBulk().ToList();
                foreach (var testData in lastBulk)
                {
                    results[testData.Id].Add(testData);
                }
                Console.WriteLine("Doing Last Read {0}", lastBulk.Count);
                long[] value = new long[UseThreads];
                long totalCount = 0;
                int errorCount = 0;
                for (int i = 0; i < UseThreads; i++)
                {
                    value[i] = AddedItems[i];
                    totalCount += value[i];
                    Console.WriteLine("Thread {0} Push {1} Items", i, value[i]);
                    var verifyArray = results[i].OrderBy(p => p.Value).ToList();
                    if (verifyArray.Count != value[i])
                    {
                        Console.WriteLine("Not Working Count miss match");
                        errorCount++;
                    }
                    else
                    {
                        var expected = 0;
                        foreach (var testData in verifyArray)
                        {
                            if (expected != testData.Value)
                            {
                                Console.WriteLine("NotWorking");
                                errorCount++;
                            }
                            expected++;
                        }
                    }
                }
                Console.WriteLine("Done Total Push {0} with {1} errors.", totalCount.ToString("#,##0") , errorCount);
                if (errorCount != 0)
                {
                    Console.ReadKey();
                }
            }
        }
    }
    private static void PushTestData(object o)
    {
        object[] parms = o as object[];
        int id = (int)parms[0];
        IBulkCollector<TestData> bulkCollector = (IBulkCollector<TestData>)parms[1];
        CountdownEvent endEvetn = (CountdownEvent)parms[2];
        AddedItems[id] = 0;
        var start = DateTime.Now;
        while ((DateTime.Now - start) < Duration)
        {
            bulkCollector.Add(new TestData() { Id = id, Value = AddedItems[id]});
            AddedItems[id]++;
        }
        endEvetn.Signal();
    }
}

lock free BulkCollector and FatalExecutionEngineError except

对不起,是一个有缺陷的内存模块引起的问题,已更换,问题已解决。

相关文章:
  • 没有找到相关文章