c# - Thread safe assigning of the returned result of a threaded function to a variable -
i have function takes variable parameter , returns calculated result. function splits other functions each doing own calculation. need function run multi threaded.
my code:
for (int = 0; < pic.width; i++) { (int k = 0; k < pic.height; k++) { var localk = k; var locali = i; image bestpic; new thread(() => { bestpic = new bitmap(getbestpic(argb));//this wrong values assigned because of cross threading lock (thislock) { g.drawimage(bestpic, locali * bestpic.width, localk * bestpic.height, bestpic.width, bestpic.height); } }).start(); } }
all need function getbestpic run multi threaded. how run function getbestpic multi threaded , make assigning of returned result bestpic variable atomic?
my entire program if needed: montage program.
using system; using system.collections.generic; using system.componentmodel; using system.data; using system.drawing; using system.linq; using system.text; using system.threading.tasks; using system.windows.forms; using system.threading; using system.drawing; namespace test { public partial class form1 : form { private static readonly object thislock = new object(); private graphics g; private bitmap returnimg; private bitmap pic; private int done = 0; private int picturewidthandlength = 200; private string inputpicname = "test"; public form1() { initializecomponent(); } private void button1_click(object sender, eventargs e) { datetime dtstart = datetime.now; pic = new bitmap(inputpicname + ".jpg"); //messagebox.show(pic.getpixel(1,1).toargb().tostring()); //messagebox.show(pic.width.tostring() + " x " + pic.height.tostring()); returnimg = new bitmap(pic.width * picturewidthandlength, pic.height * picturewidthandlength); using (g = graphics.fromimage(returnimg)) { color clr; int[] argb = new int[4]; (int = 0; < pic.width; i++) { (int k = 0; k < pic.height; k++) { clr = pic.getpixel(i, k); argb[0] = clr.a; argb[1] = clr.r; argb[2] = clr.g; argb[3] = clr.b; var localk = k; var locali = i; image bestpic; if (cbxthreading.checked) { new thread(() => { bestpic = new bitmap(getbestpic(argb)); lock (thislock) { g.drawimage(bestpic, locali * bestpic.width, localk * bestpic.height, bestpic.width, bestpic.height); done++; } }).start(); } else { //single threaded bestpic = new bitmap(getbestpic(argb)); g.drawimage(bestpic, locali * picturewidthandlength, localk * picturewidthandlength, picturewidthandlength, picturewidthandlength); } //messagebox.show(getbestpic(argb)); } } if (cbxthreading.checked) { int loopnum = pic.width * pic.height; while (done < loopnum) { } } } datetime dtend = datetime.now; messagebox.show((dtend - dtstart).tostring()); } //get picture best suited replace pixel private string getbestpic(int[] argb) { int numofpics = 5; int[] currentbest = new int[2]; currentbest[0] = 255; currentbest[1] = 150; (int = 0; < numofpics; i++) { int compare = compareargb(getaveragergb(new bitmap((i + 1).tostring()+".jpg")), argb); if (compare < currentbest[0]) { currentbest[0] = compare; currentbest[1] = + 1; } } return currentbest[1].tostring() + ".jpg"; } // smaller value, closer camparison private int compareargb(int[] one, int[] two) { int [] tmp = new int[4]; tmp[0] = convert.toint32(math.abs(one[0] - two[0])); tmp[1] = convert.toint32(math.abs(one[1] - two[1])); tmp[2] = convert.toint32(math.abs(one[2] - two[2])); tmp[3] = convert.toint32(math.abs(one[3] - two[3])); return (tmp[0] + tmp[1] + tmp[2] + tmp[3]); } //return int arry size 4 containing argb values private int[] getaveragergb(bitmap img) { color clr; int aplha = 0; int red = 0; int green = 0; int blue = 0; (int = 0; < img.width; i++) { (int k = 0; k < img.height; k++) { clr = img.getpixel(i, k); aplha += clr.a; red += clr.r; green += clr.g; blue += clr.b; } } aplha = aplha / (img.width * img.height); red = red / (img.width * img.height); green = green / (img.width * img.height); blue = blue / (img.width * img.height); int[] re = new int[] {aplha,red,green,blue}; return re; } private void button2_click(object sender, eventargs e) { returnimg.save(inputpicname+".bmp"); messagebox.show("done!"); } } }
the single thread functionality works, takes long. multi threaded functionality finishes in third of time of single threaded, result not correct.
getbestpic()
method runs multi-thread understand. problem argb
parameter. initialize ones , overwrite values in loops.argb
reference type, reference passed getbestpic()
, it's referenced values changed while processed in getbestpic()
. try pass value or move int[] argb = new int[4];
line inside of second loop, every time initialize new variable. more on passing reference type params here.
Comments
Post a Comment