【问题标题】:Thread.Join status/breakoutThread.Join 状态/突破
【发布时间】:2018-08-08 09:45:20
【问题描述】:

您好,有什么方法可以从 Thread.Join 获取线程的状态,或者我可以在指定的时间段从 Thread.Join 进行突破吗? 例如:

我有一个有 n 个作业的循环,我有 3 个空闲内核用于 3 个并行线程,在加入 3 个线程后,我想知道是否有办法检查一个线程是否完成了它的工作来启动另一个在它的地方工作。 我想让 3 个内核一直工作,而不是等待所有线程停止然后再启动另外 3 个。

【问题讨论】:

    标签: c# multithreading thread-safety


    【解决方案1】:

    最简单,也是最好的解决方案是使用线程池。线程池会根据可用的处理器和内核自动扩展。

    ThreadPool.QueueUserWorkItem(state => TaskOne());
    ThreadPool.QueueUserWorkItem(state => TaskTwo());
    ThreadPool.QueueUserWorkItem(state => TaskThree());
    ThreadPool.QueueUserWorkItem(state => TaskFour());
    

    如果您需要以困难的方式执行此操作,您可以保留待处理任务的队列和当前正在运行的任务列表,并为 Join() 调用设置超时,以便它返回如果线程没有准备好,则返回 false。

    我想不出任何理由更喜欢复杂的解决方案而不是简单的解决方案,但当然可能有。

    var MAX_RUNNING = 3;
    var JOIN_TIMEOUT_MS = 50;
    var waiting = new Queue<ThreadStart>();
    var running = new List<Thread>();   
    
    waiting.Enqueue(new ThreadStart(TaskOne));
    waiting.Enqueue(new ThreadStart(TaskTwo));
    waiting.Enqueue(new ThreadStart(TaskThree));
    waiting.Enqueue(new ThreadStart(TaskFour));
    
    
    while (waiting.Any() || running.Any())
    {
        while (running.Count < MAX_RUNNING && waiting.Any())
        {
            var next = new Thread(waiting.Dequeue());
            next.Start();
            running.Add(next);
        }
    
        for (var i = running.Count - 1; i >= 0; --i)
        {
            var t = running[i];
    
            if(t.ThreadState == System.Threading.ThreadState.Stopped) {
                running.RemoveAt(i);
                break;
            }
    
            if (t.Join(JOIN_TIMEOUT_MS))
            {
                running.RemoveAt(i);
                break;
            }
        }   
    }
    

    【讨论】:

    • 顺便说一句,您可能希望循环两次任务,首先删除所有停止的任务,然后 然后 join 依次执行它们。如果列表中的第一个任务停止,这将防止在下一个任务开始之前加入超时。但是代码也会有点难以理解。总而言之,选择简单的解决方案:)
    • 我不使用线程池的主要原因是我不知道如何在调用线程池后阻止 MainThread 运行其余代码。谢谢你的时间! :)
    • 在每个工作项中创建一个Task对象,在主线程中做Task.WaitAll()?意味着您必须在每个工作项中执行一次 try/catch 才能使任务失败,但这并不太难。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    • 2020-07-09
    • 1970-01-01
    • 2022-07-20
    • 2016-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多