c# - BeginInvoke causes error due to skipped null check -
i encountered me not understandable error caused using dispatcher.begininvoke within multi-threaded application.
my program contains list of objects through loop using multiple threads , perform calculations. have simplified (and modified) code structure bare essentials, easier understand:
public class foo { public void docalc() { //do calculations } } public class foo2 { public foo foo = new foo(); public ellipse ellipse; } public partial class mainwindow : window { list<foo2> mylist = new list<foo2>(); list<tuple<int, int>> indiceslist = new list<tuple<int, int>>(); public mainwindow() { initializecomponent(); (int = 0; < 10; ++i) mylist.add(new foo2 { ellipse = new ellipse() }); (int = 10; < 20; ++i) mylist.add(new foo2()); indiceslist.add(new tuple<int, int>(0, 9)); indiceslist.add(new tuple<int, int>(10, 19)); } private void onstart(object sender, routedeventargs e) { foreach (var t in indiceslist) threadpool.queueuserworkitem(new waitcallback(loop), t); } private void loop(object o) { tuple<int, int> indices = o tuple<int, int>; for(int = indices.item1; <= indices.item2; ++i) { mylist[i].foo.docalc(); if (mylist[i].ellipse == null) continue; application.current.dispatcher.begininvoke(dispatcherpriority.normal, new action(() => mylist[i].ellipse.fill = brushes.black)); } } } the first half of items in mylist has ellipse point actual objects, while second half points null. within loop check @ every iteration if ellipse null , skip iteration if necessary. weird in second thread ellipses point null, program still ends calling begininvoke action on first item (index 10), causing program crash, due null reference exception.
if put breakpoint on line mylist[i].foo.docalc(); , go through program step step, no error occurs. when change begininvoke invoke no error occurs.
as understand, begininvoke works asynchronously sending request dispatcher performed @ point, while invoke blocks calling thread until dispatcher has performed request. however, since neither access same elements in 2 loops, nor change list itself, don't understand how multithreading or asynchronous nature of begininvoke in way interfere doing here.
unfortunately, have found begininvoke errors connected lists when adding or removing items on so, however, nothing error occurs when threads seem access different items @ times. if code has fundamental issues not understand (which might cause program not function), please clear me or send me link answer, couldn't find. have been stuck issue whole day now!
you running in variable capture. i gets used in invoke call indices.item2 + 1 not i value had @ time did begininvoke. must copy i in local variable created new each loop itteration.
private void loop(object o) { tuple<int, int> indices = o tuple<int, int>; for(int = indices.item1; <= indices.item2; ++i) { mylist[i].foo.docalc(); if (mylist[i].ellipse == null) continue; int ilocal = i; application.current.dispatcher.begininvoke(dispatcherpriority.normal, new action(() => mylist[ilocal].ellipse.fill = brushes.black)); } } foreach prior c# 5 had same issue, see here more info.
Comments
Post a Comment