title: How does Delphi XE7 handle Multiple Threading in Parallel Tasks
body: <p>I am new to parallel programming and am trying to find out why I occasionally get an EmonitorLockException:Object lock not owned when I increase the number of parrallel tasks to run. Is the case that the Threads become tangled the more tasks I run. Or is my code code not correct?</p>
  
  <pre><code>{$APPTYPE CONSOLE}
  
  uses
  System.SysUtils, System.Threading, System.Classes, System.SyncObjs, System.StrUtils;
  
  const
  
  WorkerCount = 10000; // this is the number of tasks to run in parallel    note:when this number is increased by repeated factors of 10
                    // it takes longer to produce the result and sometimes the program crashes
                    // with an EmonitorLockException:Object lock not owned . Is it that my program is not written correctly or efficiently to run
                    // a large number of parallel taks and the Threads become entagled.
                    // Eventually I would like to optimeize the program to find the optimal number of tasks to run in parallel so as to find the result in the shortest time.
                    // This becomes important when the word sequence is increased to six or more letters.
  
  sequencetofind='help'; // letter sequence to find randomly
  sequencelengthplus1=5;  // the ength of the letter sequence plus 1 extra   letter for a check to see if it is working
  
  
  var
    Ticks: Cardinal;
    i,k,m: Integer;
    sequencenum: Integer;
    alphabetarray:array[1..26] of string;
    v:char;
    copyarray,letters:array[1..sequencelengthplus1] of string;
    tasks: array of ITask;
    LTask: ITask;
    Event1:TEvent;
    sequencesection:TCriticalSection;
  
    function findsequencex(index: Integer): TProc;    
    begin
      Result := procedure
                var
                  counter,m:integer;
                  r:integer;
                  z:string;
                  lettersx:array[1..sequencelengthplus1] of string;
                begin
                  for m:=1 to sequencelengthplus1-1 do
                    lettersx[m]:=letters[m];
                  randomize;
                  counter:=1;
                  repeat
                    r:=random(26)+1;
                    z:=alphabetarray[r];              //randomly find letters until matched    with the sequence
  
                    if z=letters[counter] then 
                    begin
                      copyarray[counter]:=z;
                      counter:=counter+1;      // increase counter when successfully found a match
                    end
                    else 
                      counter:=1;       // if match fails start again and look for the first letter
  
                    if (counter=sequencelengthplus1) then 
                    begin      // if all letters found in correct order find one more letter as a check
  
                      sequencesection.Acquire;                   //critical                  section start
                      r:=random(26)+1;
                      z:=alphabetarray[r];
  
                      TInterlocked.CompareExchange(sequencenum,r,0);
                      copyarray[sequencelengthplus1]:=z;
                      Event1.SetEvent;                                 // set in motion the process to stop all other tasks
                      sequencesection.release;                    // critical section end
                    end;
                  until (Event1.WaitFor(0)=wrSignaled);      // check to see if all letters of the sequence has been found
                end;
    end;
  
  
  
    procedure Parallel2;
    var
      i,sequencevalue,j: Integer;
    begin
      Event1:=TEvent.Create(nil,true,false,'noname');    // sequence checker
      Event1.resetevent;
      sequencenum := 0;
      Ticks := TThread.GetTickCount;
      SetLength(Tasks, WorkerCount);             // number of parallel tasks to undertake
      for i := 0 to WorkerCount-1 do
        Tasks[i]:=TTask.Run(findsequencex(i));
      TTask.WaitForAny(Tasks);             // wait for the first one to   successfully finish
      TThread.Synchronize(nil,
                 procedure
                 begin
                   for LTask in Tasks do
                     LTask.Cancel;                                  // kill   the remaining tasks
                   TInterlocked.Add (sequencevalue, sequencenum);   // note   the random letter check
                 end);
      Ticks := TThread.GetTickCount - Ticks;
      writeln('Parallel time ' + Ticks.ToString + ' ms, last random alphabet sequence number: ' + sequencenum.ToString+' random letter is = '+alphabetarray[sequencevalue]);
    end;
  begin
    sequencesection:=TCriticalSection.Create;
    for m:=1 to  (sequencelengthplus1-1) do
    begin
      letters[m]:=copy(sequencetofind,m,1);
      writeln(letters[m]);
    end;
    i:=0;
    for v:='a' to 'z' do
    begin
      i:=i+1;
      alphabetarray[i]:=v;
    end;
    try
      begin
        Parallel2;    // call the parrallel procedure
        writeln('finished');
       for m:=1 to sequencelengthplus1 do
         writeln(copyarray[m]);
       if (Event1.WaitFor(0)=wrSignaled) then 
       begin
         writeln('event signaled');
         if (sequencenum=0) then writeln('sequence is null');
       end;
       Event1.Free;
       sequencesection.free;
     end;
    except
      on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
    end;
    Readln;
   end.
  </code></pre>