【问题标题】:Switching between threads在线程之间切换
【发布时间】:2015-05-19 15:31:44
【问题描述】:

我有两个线程:

static Thread thread1 = new Thread(new ThreadStart(Team1Shots));
static Thread thread2 = new Thread(new ThreadStart(Team2Shots));

我想让 thread1 做一些工作(但未完成),然后 thread2 做一些工作(但未完成),然后返回完成 thread1,然后返回完成 thread2。

到目前为止我有这个:

static void Main(string[] args)
{
    thread1.Start();
}

private static void Team1Shots()
{
   //Do Work in here...then

   thread2.Start();
   thread2.Join(); //Go to thread2

   //When join in thread2 to here
   //Do the rest of the work

   //Get thread2 to finish
}

private static void Team2Shots()
{
   //Do Work in here...
   thread1.Join(); //Go back to thread1

   //When thread1 finishes
   //Do the rest of the work

   // Finished All work
}

这不起作用,不知道从这里去哪里。

【问题讨论】:

  • 您应该使用信号量或互斥锁来同步多个线程。 Thread.Join 不进行切换(它将这个线程连接到现有的线程,阻塞直到它完成)。您也可以使用 ManualResetEvent 或临界区(锁),有很多选项取决于您需要做什么。
  • 顺便说一下,根据 cmets,您描述了一种不可能的情况。线程1启动线程2,等待一段时间,然后线程2“切换”回线程1,做更多的工作然后等待线程2,但线程2正在等待线程1。它的编码方式是死锁,它描述的方式是活锁。

标签: c# multithreading join


【解决方案1】:

由于您实际上从不希望任何工作并行完成,而是一次只让其中一个工作,所以您不应该有两个线程。有一个线程先做所有应该做的事情,然后是所有应该做的事情,然后是所有接下来应该做的事情,依此类推。您通过创建多个线程来启动/停止彼此的进程,从而不必要地创建工作。

【讨论】:

    【解决方案2】:

    您可以使用BlockingCollection(T) 在线程之间进行通信。将这些步骤建模为状态机,您可以在线程之间对消息进行 ping-pong。

    // States
    public enum MessageType
    {
        Done,
        Work1,
        Work2,
        Work3,
        Work4
    }
    
    // Data
    public class WorkerStateMessage
    {
        public static readonly WorkerStateMessage Done =
            new WorkerStateMessage { Type = MessageType.Done };
        public MessageType Type { get; set; }
        public string Progress { get; set; }
        public int Data { get; set; }
    }
    

    主要

    static Thread thread1 = new Thread(new ThreadStart(Team1Shots));
    static Thread thread2 = new Thread(new ThreadStart(Team2Shots));
    static BlockingCollection<WorkerStateMessage> thread1Messages =
        new BlockingCollection<WorkerStateMessage>();
    static BlockingCollection<WorkerStateMessage> thread2Messages =
        new BlockingCollection<WorkerStateMessage>();
    static BlockingCollection<WorkerStateMessage> progressMessages =
        new BlockingCollection<WorkerStateMessage>();
    
    static void Main(string[] args)
    {
        thread1Messages.Add(new WorkerStateMessage { Type = MessageType.Work1, Data = 1 });
        thread1Messages.Add(new WorkerStateMessage { Type = MessageType.Work1, Data = 2 });
        thread1Messages.Add(new WorkerStateMessage { Type = MessageType.Work1, Data = 3 });
        thread1.Start();
        thread2.Start();
        // 4 step * 3 messages = 12 progress messages
        foreach(var message in progressMessages.GetConsumingEnumerable().Take(12))
        {
            Console.WriteLine(message.Progress);
            Console.WriteLine("Current data: {0}", message.Data);
        }
    
        thread1Messages.Add(WorkerStateMessage.Done);
        thread2Messages.Add(WorkerStateMessage.Done);
        thread1.Join();
        thread2.Join();
    }
    

    线程 1

    private static void Team1Shots()
    {
        foreach(var message in thread1Messages.GetConsumingEnumerable())
        {
            WorkerStateMessage nextMessage;
            switch(message.Type)
            {
                case MessageType.Work1:
                    var added = message.Data + 1;
                    nextMessage = new WorkerStateMessage
                    {
                        Type = MessageType.Work2, 
                        Progress = "Add 1",
                        Data = added
                    };
                    progressMessages.Add(nextMessage);
                    thread2Messages.Add(nextMessage);
                break;
                case MessageType.Work3:
                    var multiplied = message.Data + 1;
                    nextMessage = new WorkerStateMessage
                    {
                        Type = MessageType.Work4,
                        Progress = "Multiply by 2",
                        Data = multiplied
                    };
                    progressMessages.Add(nextMessage);
                    thread2Messages.Add(nextMessage);
                break;
                default:
                    return;
            }
        }
    }
    

    线程 2

    private static void Team2Shots()
    {
       foreach(var message in thread2Messages.GetConsumingEnumerable())
        {
            WorkerStateMessage nextMessage;
            switch(message.Type)
            {
                case MessageType.Work2:
                    var added = message.Data + 2;
                    nextMessage = new WorkerStateMessage
                    {
                        Type = MessageType.Work3,
                        Progress = "Add 2",
                        Data = added
                    };
                    progressMessages.Add(nextMessage);
                    thread1Messages.Add(nextMessage);
                break;
                case MessageType.Work4:
                    var divided = message.Data / 2;
                    nextMessage = new WorkerStateMessage 
                    {
                        Type = MessageType.Work3,
                        Progress = "Divide by 2",
                        Data = divided
                    };
                    progressMessages.Add(nextMessage);
                    thread2Messages.Add(nextMessage);
                break;
                default:
                    return;
            }
        }
    }
    

    输出

    Add 1
    Current data: 2
    Add 1
    Current data: 3
    Add 1
    Current data: 4
    Add 2
    Current data: 4
    Add 2
    Current data: 5
    Add 2
    Current data: 6
    Multiply by 2
    Current data: 5
    Multiply by 2
    Current data: 6
    Multiply by 2
    Current data: 7
    Divide by 2
    Current data: 2
    Divide by 2
    Current data: 3
    Divide by 2
    Current data: 3
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-17
      • 1970-01-01
      • 2015-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多