Home > Mobile >  Best practice to have a thread wait on an object to be updated
Best practice to have a thread wait on an object to be updated

Time:07-30

I am doing some unit tests and I would like to have a way to have tasks that are already running waiting on given values that the task doing the tests could change at will.

So I have multiple tasks that start running and doing their stuff, then I want to interrupt them midway so that other threads can be at the same stage. Then check my object is in the expected state, then the thread can run its course.

I know I can do that using a while loop and a boolean, however, I'd like to know if there are better ways to have threads waiting on an update from other threads.

basically, the code would be something along those lines:

public void Test() {
    Task.Run(() => {
        // Do Stuff
        // wait the main thread
        // Do Stuff
    })
    Task.Run(() => {
        // Do Stuff
        // wait the main thread
        // Do Stuff
    })

    // Check some stuff
    // signals the tasks to stop waiting
    // Check other stuff
}

Thank you for your time.

CodePudding user response:

Based on description sounds like an appropriate place to use Barrier:

var barrier = new Barrier(3);

var task1 = Task.Run(() =>
{
    Console.WriteLine("before sync 1");
    barrier.SignalAndWait();
    Console.WriteLine("after sync 1");
});

var task2 = Task.Run(async () =>
{
    await Task.Delay(100);
    Console.WriteLine("before sync 2");
    barrier.SignalAndWait();
    Console.WriteLine("after sync 2");
});

var task3 = Task.Run(async () =>
{
    await Task.Delay(500);
    Console.WriteLine("before sync 3");
    barrier.SignalAndWait();
    Console.WriteLine("after sync 3");
});

await Task.WhenAll(task1, task2, task3);

Will print something like:

before sync 1
before sync 2
before sync 3
after sync 3
after sync 1
after sync 2

But depended on actual use case some other synchronization primitive can be preferable (see overview of synchronization primitives and threading in C# by ​Joseph Albahari).

CodePudding user response:

There is ManualResetEvent(Slim) that can be used to provide signaling between threads. These can be used in pairs to get fine grained control over the execution:

var signalX= new ManualResetEventSlim(false);
var waitX= new ManualResetEventSlim(false);

var task = new Task.Run(() => {
    // do something
    signalX.Set();
    waitX.Wait();
    // Do something else
});
signalX.Wait();
// Verify state
waitX.Set();

  • Related