Ссылка на объект C # возвращает ИНОСТРАННЫЕ потери в потоках, заканчивающихся через EventHandler - PullRequest
0 голосов
/ 01 июня 2018

У меня странная проблема со следующим кодом, который запускается примерно каждую минуту.Обычно все работает нормально, но иногда функция HandleCalcStatistikMarkersDone вызывает ошибку из-за NullReferenceException.

Я пытаюсь объяснить с помощью кода:

У меня есть класс Strategies .Этот класс запускается каждую минуту для вычисления и обновления некоторой информации в базе данных MySQL.Этот класс создается несколько раз в отдельных потоках внутри тикера в форме.

public partial class mainForm: Form
{
//do something including ticker, that starts RunStatistik about every minute after the previous thread ended

   private void RunStatistik()
    {            
        foreach (InternalObject objPar in InternalObjects)
        {
            Strategies.StrategyParameter giveParms = new Strategies.StrategyParameter();
            giveParms.pair= objPar.pair;

            Strategies strat = new Strategies();
            Thread calcStatistikThread = new Thread(new ParameterizedThreadStart(strat.CalcCoinStatistik));
            calcStatistikThread.Start(giveParms);

        }
    }
}

Внутренне в верхнем инициированном потоке стратегий есть несколько дополнительных потоков.Эти потоки имеют «DoneEvent», которое вызывается в конце функции.

Чтобы заметить, что все потоки закончились до окончания основного потока, я собираю все подпотоки в список CalcStatistikMarkersThreads и жду, пока списокпустой.Субпотоки должны удалить себя из верхнего списка через событие ThreadDone.Но иногда искомый поток (CalcStatistikMarkersThreads.Find) больше не обнаруживается, и я получаю исключение NullReferenceException.Вопрос в том, почему?!

Не могли бы вы сказать мне, почему?А возможно как предотвратить?

Заранее спасибо.

class Strategies
{   public event EventHandler ThreadDone;
    private List<Thread> CalcStatistikMarkersThreads;

//do something

    public void CalcCoinStatistik(object parameters)
    {
    StrategyParameter givenParms = (StrategyParameter)parameters;
    Pair internalPair = givenParms.pair

    //do something

        if (CalcStatistikMarkersThreads == null)
        {
            CalcStatistikMarkersThreads = new List<Thread>();
        }

        foreach (InternalTodo in InternalToDos)
        {
            Strategies strat = new Strategies();
            CalcStatistikMarkersParameter csp = new CalcStatistikMarkersParameter();
            csp.parm1 = param;

            strat.ThreadDone += HandleCalcStatistikMarkersDone;

            Thread candleCalc = new Thread(new ParameterizedThreadStart(strat.CalcStatistikMarkers));

            CalcStatistikMarkersThreads.Add(candleCalc);
            candleCalc.Start(csp);

            while (CalcStatistikMarkersThreads.Count != 0)
            {                   
                Task.Delay(1000).Wait();                    
            }                 
        }        
    }

    public void CalcStatistikMarkers(object parm)
    {
    //do something      

        if (ThreadDone != null)
            ThreadDone(this, new ThreadInfoEventArgs(Thread.CurrentThread.ManagedThreadId));
    }

    public void HandleCalcStatistikMarkersDone(object sender, EventArgs e)
    {
        Guid workGUID = Guid.NewGuid();
        ThreadInfoEventArgs tEv = (ThreadInfoEventArgs)e;
        Thread currentThread;

        try
        {
            currentThread = CalcStatistikMarkersThreads.Find(xy => xy.ManagedThreadId == tEv.ThreadID);
            //HERE THE NullReferenceException is raised sometimes
            CalcStatistikMarkersThreads.Remove(currentThread);
        }
        catch (Exception ex)
        {
            throw ex;
        }            
    }


    public class ThreadInfoEventArgs : EventArgs
    {
        private int threadID;
        public ThreadInfoEventArgs(int trID)
        {
            this.threadID = trID;
        }
        public int ThreadID
        {
            get { return threadID; }
        }
    }

}

Cheers Air

...