C#对象引用有时会在通过EventHandler结束的线程中丢失
我有一个奇怪的问题,下面的代码,这是每分钟开始。 正常情况下,一切正常,但有时HandleCalcStatistikMarkersDone函数会因NullReferenceException而引发错误 我试着用代码来解释: 我有一门课策略。这个类大约每分钟都会开始计算和更新MySQL数据库中的一些信息。该类在表单的ticker中的单独线程中多次实例化C#对象引用有时会在通过EventHandler结束的线程中丢失,c#,.net,multithreading,events,nullreferenceexception,C#,.net,Multithreading,Events,Nullreferenceexception,我有一个奇怪的问题,下面的代码,这是每分钟开始。 正常情况下,一切正常,但有时HandleCalcStatistikMarkersDone函数会因NullReferenceException而引发错误 我试着用代码来解释: 我有一门课策略。这个类大约每分钟都会开始计算和更新MySQL数据库中的一些信息。该类在表单的ticker中的单独线程中多次实例化 public partial class mainForm: Form { //do something including ticker, th
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; }
}
}
}
课堂策略
{公共事件事件处理程序ThreadDone;
私有列表CalcStatistikMarkersThreads;
//做点什么
public void CalccInstantik(对象参数)
{
StrategyParameter givenParams=(StrategyParameter)参数;
Pair internalPair=givenParms.Pair
//做点什么
if(CalcStatistikMarkersThreads==null)
{
CalcStatistikMarkersThreads=新列表();
}
foreach(InternalToDos中的InternalTodo)
{
战略战略战略=新战略();
CalcStatistikMarkersParameter csp=新的CalcStatistikMarkersParameter();
csp.parm1=参数;
strat.ThreadDone+=HandleCalcStatistikMarkersDone;
Thread candleCalc=新线程(新的参数化ThreadStart(strat.calcstatitikmarkers));
添加(candleCalc);
烛光启动(csp);
while(CalcStatistikMarkersThreads.Count!=0)
{
Task.Delay(1000.Wait();
}
}
}
公共无效CalcStatistikMarkers(对象参数)
{
//做点什么
if(ThreadDone!=null)
ThreadDone(这是新的ThreadInfoEventArgs(Thread.CurrentThread.ManagedThreadId));
}
public void HandleCalcStatistikMarkersDone(对象发送方,事件参数e)
{
Guid workGUID=Guid.NewGuid();
ThreadInfoEventArgs tEv=(ThreadInfoEventArgs)e;
线程当前线程;
尝试
{
currentThread=CalcStatistikMarkersThreads.Find(xy=>xy.ManagedThreadId==tEv.ThreadID);
//此处有时会引发NullReferenceException
CalcStatistikMarkersThreads.Remove(currentThread);
}
捕获(例外情况除外)
{
掷骰子;
}
}
公共类ThreadInfoEventArgs:EventArgs
{
私有int-threadID;
公共线程信息事件参数(int trID)
{
this.threadID=trID;
}
公共int线程ID
{
获取{return threadID;}
}
}
}
干杯
Air我假设使用try-catch处理异常不会有帮助,因为您希望解决问题的原因,而不仅仅是处理场景。如果在有问题的情况下调试
CalcStatistikMarkersThreads
是完全空的,或者只是不包含特定的线程?使用visual studio调试这一点有点问题。我只有生产系统的问题。我在CalcStatistikMarkersThreads上记录了一个.Count。它表明变量中填充了正确的数字。然后,当我尝试通过为CalcStatistikMarkersThreads中的每个线程迭代线程时,它还会抛出一个NullReferenceException