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

Popular posts from this blog

Rendering JButton to get the JCheckBox behavior in a JTable by using images does not update my table -

javascript - Using jquery append to add option values into a select element not working -

Android soft keyboard reverts to default keyboard on orientation change -