C#多线程处理-等待方法完成,然后再次运行

时间:2020-05-31 09:23:19

标签: c# .net multithreading

我有一个看起来像这样的方法:

while(intVariable < 4))
        {
            DoSomeStuff();

            if (intVariable == 3)
            {
                FinalDecide();
            }

            if (rollCounter < 3)
            {
                Decide(args);
            }
            intVariable++;
        }

方法Decide()运行32个线程,我想确保在循环第二次开始Decide()之前,第一次完成

在内部决策中,我有这样的东西:

for (int i = 0; i < 32; i++)
        {
            Thread t = new Thread(new ParameterizedThreadStart(Prepare));
            t.IsBackground = true;
            t.Start(i);
        }

        runner = new System.Threading.Thread(WaitforThreads);
        runner.IsBackground = true;
        runner.Start();

即使我等待这32个线程在本次Decide方法运行中完成,该代码仍会继续运行,并在第一个方法完成之前再次触发Decide方法,这会导致错误

如何确保方法Decide在第二次启动之前完成WaitforThreads()方法?

1 个答案:

答案 0 :(得分:1)

一种实现此目的的方法是使Decide方法返回已启动线程的Thread[]并将其保存到while循环可访问的变量中,然后在下次调用Decide之前加入所有线程:

Thread[] decideThreads = null;
while(intVariable < 4))
        {
            DoSomeStuff();

            if (intVariable == 3)
            {
                FinalDecide();
            }

            if (rollCounter < 3)
            {
                if (decideThreads != null)
                {
                    foreach (var t in decideThreads)
                        t.Join();
                }
                decideThreads = Decide(args);
            }
            intVariable++;
        }

更好的是,您可以按照注释中的建议用Task<T>替换线程,然后只返回Task.WhenAll而不是Thread[]。然后,您可以使用async使代码更有效:

Task decideTask = null;
while(intVariable < 4))
        {
            DoSomeStuff();

            if (intVariable == 3)
            {
                FinalDecide();
            }

            if (rollCounter < 3)
            {
                if (decideTask != null)
                    await decideTask;

                decideTask = Decide(args);
            }
            intVariable++;
        }

Decide然后将执行以下操作:

Task[] workers = new Task[32];
for (int i = 0; i < 32; i++)
        {
            var localI = i; // to be captured in lambda
            workers[i] = new Task(() => Prepare(localI));
        }

return Task.WhenAll(workers);