Synchronize Threads

Asked

Viewed 933 times

3

I have a 3-thread application, this application involves a chemical process simulator, and I have to take some values of these processes. values come in a single object.

The 3 threads make an infinite loop, in this loop they take the values at different times, which cannot happen.

I wanted to know if there’s any way I can synchronize the threads, so when they go to pick up the object all 3 pick up at the same time.

Here are my threads:

public void RunController()
{
     Softing.OPCToolbox.Client.Application app = Softing.OpcToolbox.Client.Application.Instance;
     app.Initialize();
     while(true)
     {
          scase.Solver.Integrator.IsRunning = true;
          Thread.Sleep(1000);
          scase.Solver.Integrator.IsRunning = false;
          scase = Interaction.GetObject(opcform.pasta);
          Contrl();
          GC.Collect();
     }
}




public void RunExport()
{
     Softing.OPCToolbox.Client.Application app = Softing.OpcToolbox.Client.Application.Instance;
     app.Initialize();
     while(true)
     {
          scase.Solver.Integrator.IsRunning = true;
          Thread.Sleep(1000);
          scase.Solver.Integrator.IsRunning = false;
          scase = Interaction.GetObject(opcform.pasta);
          Exprt();
          GC.Collect();
     }
}



public void RunImport()
{
     Softing.OPCToolbox.Client.Application app = Softing.OpcToolbox.Client.Application.Instance;
     app.Initialize();
     while(true)
     {
          scase.Solver.Integrator.IsRunning = true;
          Thread.Sleep(1000);
          scase.Solver.Integrator.IsRunning = false;
          scase = Interaction.GetObject(opcform.pasta);
          Imprt();
          GC.Collect();
     }
}

I’d like them to execute the scase = Interaction.GetObject(opcform.pasta); at the same time.

  • What do you mean, "all three take at the same time"? You want to make a state machine that, with each iteration, the 3 use the same input?

  • exact! suggested that I create a thread and that it is in the infinite loop, it would take the object and send to the threads, that would be initiated and aborted at each turn of the infinite loop

  • Is this process too heavy? Will it run for a long time with each iteration? Or is it something more or less simple?

  • depends on the computer, the ones I’ve been using the longest thread takes about 20 seconds to give each turn

  • Is there any reason to call GC.Collect()? You know you’re only supposed to call him if you know what he’s doing and you have a very strong reason. In general not applied in codes in production and even more in loops.

  • I was warned this and I put a condition not to do it every time, what was happening was a memory Leak and an access error in protected memory region, the GC.Colect() helped with both. If you have any material that talks more about this I will be very grateful

Show 1 more comment

1 answer

2


Given the problem you’re facing, I don’t think it’s interesting that you create Threads that way. You’d be dealing with unnecessary competition.

You have entries, jobs that need to be executed (maybe in parallel, maybe not), and waiting for outputs. This is a typical example of using Tasks in C#, which may or may not be executed in parallel.

This article is very interesting of how tasks can be used: http://msdn.microsoft.com/en-us/library/dd537609%28v=vs.110%29.aspx

Take this example:

using System;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
        Task<Double>[] taskArray = { Task<Double>.Factory.StartNew(() => DoComputation(1.0)),
                                     Task<Double>.Factory.StartNew(() => DoComputation(100.0)), 
                                     Task<Double>.Factory.StartNew(() => DoComputation(1000.0)) };

        var results = new Double[taskArray.Length];
        Double sum = 0;

        for (int i = 0; i < taskArray.Length; i++) {
            results[i] = taskArray[i].Result;
            Console.Write("{0:N1} {1}", results[i], 
                              i == taskArray.Length - 1 ? "= " : "+ ");
            sum += results[i];
        }
        Console.WriteLine("{0:N1}", sum);
   }

   private static Double DoComputation(Double start)
   {
      Double sum = 0;
      for (var value = start; value <= start + 10; value += .1)
         sum += value;

      return sum; 
   }
}

This example starts the calculation in 3 distinct tasks. When adding the value, using the result task.Result, If the task is not finished, it waits until the end of its execution without stopping the others. Note that a synchronization is not required. You pass the values, they produce a result.

You can literally make a loop for and do when iterations you want. With each iteration, he re-launches the 3 tasks in parallel and re-joins the result.

  • your code seems to solve my problem, but forgive my ignorance, I could not see where it awaits the completion of the execution, this explicit?

  • @Yanjovita at exactly the time he tries to access Result. You can explicitly ask him to wait for the results or try to access Result. Cool right?

  • Yes, it looks good like this, we can take your code as a basis to solve my problem. Thank you!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.