-1

I have two threads. First of them implements two methods, second only one. I need to synchronize threads this way: implementation of first method from first thread, implementation of method from second thread, implementation of second method from first thread. I tried to use barrier but it doesn't help:

bool complete = false;

// Start tasks
Task task_1 = factory.StartNew(() =>
{
    Console.WriteLine("1");
    Thread.MemoryBarrier();
    if (complete)
    {
        Console.WriteLine("3");
    }
});

Task task_2 = factory.StartNew(() =>
{
    //Thread.MemoryBarrier();    // Barrier 3
    Console.WriteLine("2");
    Thread.MemoryBarrier();    // Barrier 1
    complete = true;
    Thread.MemoryBarrier();
});
task_2.Wait();

How can I solve this?

Thank you very much!

Thank you for all your posts. I tried to use barrier class but the result is not which I need. I will try to explain my problem. I have few threads in which are called two or more methods:

 Barrier barrier = new Barrier(2); // 2 = #threads participating.
            bool complete = false;
            TaskFactory factory = Task.Factory;

            // Start tasks
            Task task_1 = factory.StartNew(() =>
            {
                process_1.Server("1 and 2");
                barrier.SignalAndWait(); // Wait for task 2 to catch up.
                barrier.SignalAndWait(); // Wait for task 2 to print "2" and set complete = true.

                if (complete)
                {
                    process_1.Server("1 and 3");
                }
            });
            Task task_6 = factory.StartNew(() =>
            {
                process_6.Server("6 and 4");
                process_6.Server("6 and 3");
            });
            Task task_2 = factory.StartNew(() =>
            {
                barrier.SignalAndWait(); // Wait for task 1 to print "1".
                process_2.Client("1 and 2");
                complete = true;
                barrier.SignalAndWait(); // Wait for task 1 to read complete as true.

                process_2.Server("2 and 5");
                process_2.Server("2 and 3");
            });
            Task task_4 = factory.StartNew(() =>
            {
                process_4.Client("6 and 4");
                process_4.Server("4 and 7");
                process_4.Server("4 and 3");
            });
            Task task_5 = factory.StartNew(() =>
            {
                process_5.Client("2 and 5");
                process_5.Server("5 and 3");
            });
            Task task_7 = factory.StartNew(() =>
            {
                process_7.Client("4 and 7");
                process_7.Server("7 and 3");
            });
            Task task_3 = factory.StartNew(() =>
            {
                process_3.Client("1 and 3");
                process_3.Client("2 and 3");
                process_3.Client("4 and 3");
                process_3.Client("5 and 3");
                process_3.Client("6 and 3");
                process_3.Client("7 and 3");
            });

            task_3.Wait();

I need to ensure consequence between calling methods from different threads for example: process_1.Server("1 and 2"); and process_2.Client("1 and 2");. Calling Client method before Server is not acceptable. All the dependencies: {process_1.Server("1 and 2"); process_2.Client("1 and 2");}, {process_2.Server("2 and 5"); process_5.Client("2 and 5");}, {process_6.Server("6 and 4"); process_4.Client("6 and 4");}, {process_4.Server("4 and 7"); process_7.Client("4 and 7");}, {process_1.Server("1 and 3"); process_3.Client("1 and 3");}, {process_2.Server("2 and 3"); process_3.Client("2 and 3");}, {process_4.Server("4 and 3"); process_3.Client("4 and 3");}, {process_5.Server("5 and 3"); process_3.Client("5 and 3");}, {process_6.Server("6 and 3"); process_3.Client("6 and 3");}, {process_7.Server("7 and 3"); process_3.Client("7 and 3");}.

Between elemets {...} and {...} there are no dependecies. So it is possible to execute {process_6.Server("6 and 3"); process_3.Client("6 and 3");}, {process_7.Server("7 and 3"); process_3.Client("7 and 3");} or vice versa {process_7.Server("7 and 3"); process_3.Client("7 and 3");}, {process_6.Server("6 and 3"); process_3.Client("6 and 3");}. There are dependencies between elements into {...} which I wrote. Can you help me to solve this problem? I can not figure out how to implement this. Thank you very much!

user3649515
  • 199
  • 7
  • 17

4 Answers4

2

Use an AutoResetEvent

AutoResetEvent waitA = new AutoResetEvent(false); //task_1 uses this to signal task_2
AutoResetEvent waitB = new AutoResetEvent(false); //task_2 uses this to signal task_1

// Start tasks
Task task_1 = Task.Run(() =>
               {
                   Console.WriteLine("1");
                   waitA.Set();
                   waitB.WaitOne();
                   Console.WriteLine("3");
               });

Task task_2 = Task.Run(() =>
               {
                   waitA.WaitOne();
                   Console.WriteLine("2");
                   waitB.Set();
               });
task_2.Wait();

Fiddle: https://dotnetfiddle.net/rnfWRZ

dcastro
  • 66,540
  • 21
  • 145
  • 155
1

The language will execute methods in order natively, take advantage of this and refactor your code

        bool complete = false;

        // Start tasks
        Task task_1 = factory.StartNew(() =>
        {
            Console.WriteLine("1");
            Console.WriteLine("2");

            if (complete)
            {
                Console.WriteLine("3");
            }

            complete = true;
        });

        task_1.Wait();

Synchronization hacks will obfuscate your code's intent. Avoid where you can!

Gusdor
  • 14,001
  • 2
  • 52
  • 64
  • I understand. I need to commenicate between threads and need synchronization. I posted an example similar to my programm. What mechanism I should use to execute first method from first thread, method from second thread, second method from first thread? – user3649515 Jun 09 '14 at 08:17
1

Assuming you want the threads to output "1, 2, 3" you can do it like this:

Barrier barrier = new Barrier(2); // 2 = #threads participating.
bool complete = false;

// Start tasks
Task task_1 = Task.Factory.StartNew(() =>
{
    Console.WriteLine("1");
    barrier.SignalAndWait(); // Wait for task 2 to catch up.
    barrier.SignalAndWait(); // Wait for task 2 to print "2" and set complete = true.
    if (complete)
    {
        Console.WriteLine("3");
    }
});

Task task_2 = Task.Factory.StartNew(() =>
{
    barrier.SignalAndWait(); // Wait for task 1 to print "1".
    Console.WriteLine("2");
    complete = true;
    barrier.SignalAndWait(); // Wait for task 1 to read complete as true.
});

task_2.Wait();
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • MSDN assigns the `Barrier` class specifically for this use - `Enables multiple tasks to cooperatively work on an algorithm in parallel through multiple phases.` – Gusdor Jun 09 '14 at 08:26
0

you are confusing task with thread as many tasks can use the some thread. from Jon Skeet answer

  1. Thread is a lower-level concept: if you're directly starting a thread, you know it will be a separate thread, rather than executing on the thread pool etc.
  2. Task is more than just an abstraction of "where to run some code" though - it's really just "the promise of a result in the future".

And MemoryBarrier is needed for the compiler to stop the reorder of instructions as compiler can decide to do optimisations.

you can do something like this to achieve the execution in the order

class Program
{
    static void Main(string[] args)
    {
        var task1 = new TaskFactory().StartNew(Method1);
        var task2 = task1.ContinueWith(delegate { Method2(); });
        var task3 = task2.ContinueWith(delegate { Method1(); });

    }

    private static void Method1()
    {

    }
    private static void Method2()
    {


    }
Community
  • 1
  • 1
BRAHIM Kamel
  • 13,492
  • 1
  • 36
  • 47