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

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

Android soft keyboard reverts to default keyboard on orientation change -

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