C#. Multithreading

本文关键字:Multithreading | 更新日期: 2023-09-27 18:07:31

我有两个线程。第一个实现了两个方法,第二个只有一个。我需要这样同步线程:从第一个线程实现第一个方法,从第二个线程实现方法,从第一个线程实现第二个方法。我试图使用屏障,但它没有帮助:

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();

我该如何解决这个问题?

非常感谢!

谢谢你所有的帖子。我试图使用barrier类,但结果不是我需要的。我会试着解释我的问题。我很少有调用两个或多个方法的线程:

 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();

我需要确保从不同线程调用方法之间的后果,例如:process_1.Server("1 and 2");process_2.Client("1 and 2");。在服务器之前调用客户端方法是不可接受的。所有依赖项:{process_1。服务器("1和2");process_2。客户端("1和2");},{process_2。服务器("2和5");process_5。Client("2 and 5");}, {process_6. 6;服务器("6和4");process_4。客户端("6和4");},{process_4。服务器("4和7");process_7。客户端("4和7");},{process_1。服务器("1和3");process_3。客户端("1和3");},{process_2。服务器("2和3");process_3。客户端("2和3");},{process_4。服务器("4和3");process_3。Client("4 and 3");}, {process_5;服务器("5和3");process_3。Client("5 and 3");}, {process_6;服务器("6和3");process_3。Client("6 and 3");}, {process_7;服务器("7和3");process_3。Client("7 and 3");}.

元素之间{…}和{…没有依赖项。因此可以执行{process_6。服务器("6和3");process_3。Client("6 and 3");}, {process_7;服务器("7和3");process_3。Client("7 and 3");},反之亦然{process_7。服务器("7和3");process_3。Client("7 and 3");}, {process_6;服务器("6和3");process_3。Client("6 and 3");}。{…是我写的。你能帮我解决这个问题吗?我想不出如何实现这个。非常感谢!

C#. Multithreading

使用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();

小提琴:https://dotnetfiddle.net/rnfWRZ

语言将按本机顺序执行方法,利用这一点并重构您的代码

        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();
同步攻击会混淆代码的意图。尽量避免!

假设您希望线程输出" 1,2,3 ",您可以这样做:

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();

你混淆了任务和线程,因为许多任务可以使用一些线程。来自Jon Skeet的回答

  1. 线程是一个较低级别的概念:如果你直接启动一个线程,你知道它将是一个单独的线程,而不是在线程池中执行。
  2. 任务不仅仅是"在哪里运行一些代码"的抽象-它真的只是"未来结果的承诺"。

编译器需要MemoryBarrier来停止指令的重新排序,因为编译器可以决定做优化。

你可以做这样的事情来实现按

顺序执行
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()
    {

    }