我需要冻结主线程直到结束递归。 递归深度=线程数。
示例代码:
BackgroundWorker backgroundWorker1;
Random ran;
private void Form1_Load(object sender, EventArgs e)
{
method();
label1.Text = "Threads is finished";
}
private void method() // recursive method
{
Thread.Sleep(100);
backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.DoWork +=
new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.RunWorkerAsync(); //Beginning new thread
}
private void backgroundWorker1_DoWork(object sender,
DoWorkEventArgs e)
{
ran = new Random();
Thread.Sleep(ran.Next(500, 1000));
if (ran.Next(1, 5) != 1) // if = 1 then to stop recursion
{
method();
}
}
线程完成后,label1.Text
的值必须为"Threads is finished"
。这是怎么做到的?
答案 0 :(得分:1)
控制台应用程序PoC,它缓存对所有已创建工作程序的引用,并使用数字变量来检查当值达到0时仍在进行的工作程序数 - 应用程序终止。如有任何问题,请通知我。
class Program
{
private static IList<BackgroundWorker> workers;
private static Random ran;
private static int activeWorkersCount;
static void Main(string[] args)
{
workers = new List<BackgroundWorker>();
DoWork();
while (activeWorkersCount > 0)
{
Thread.Sleep(200);
}
Console.WriteLine("Waiting for all workers to finish...");
Console.ReadLine();
}
private static void DoWork() // recursive method
{
Thread.Sleep(100);
var newWorker = new BackgroundWorker();
newWorker.DoWork += BackgroundWorkerDoWork;
newWorker.RunWorkerCompleted += (o, e) =>
{
Console.WriteLine("[E] Worker finished");
Interlocked.Decrement(ref activeWorkersCount);
};
Interlocked.Increment(ref activeWorkersCount);
newWorker.RunWorkerAsync();
}
private static void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine("[S] Worker started");
ran = new Random();
Thread.Sleep(ran.Next(500, 1000));
if (ran.Next(1, 5) != 1) // if = 1 then to stop recursion
{
DoWork();
}
}
}
答案 1 :(得分:0)
当您决定停止递归时,您可以将回调发布到GUI线程上。在我的头顶,它将是这样的:
if(ran.Next(1,5)!=1)
{
method();
}
else
{
Action action=()=>label1.Text = "Threads is finished";
this.BeginInvoke(action);
}
答案 2 :(得分:0)
1)创建一个更新Label1的方法:
private void WorkFinished()
{
if(Label1.InvokeRequired)
{
Label1.Invoke(WorkFinished);
}
else
{
Label1.Text = "Threads is finished";
}
}
2)从backgroundWorker1_DoWork调用WorkFinished()。
答案 3 :(得分:0)
您可以使用CountDownEvent类:
示例:
using (CountDownEvent countdownEvent = new CountdownEvent(numberOfThreads))
{
for (int threadIndex= 0; i < numberOfThreads; threadIndex++)
ThreadPool.QueueUserWorkItem(
th =>
{
DoWork();
countdownEvent.Signal();
}, threadIndex);
countdownEvent.Wait();
}
Console.WriteLine("All threads complete");
答案 4 :(得分:0)
我使用了一个易失整数,并且效果很好。
BackgroundWorker backgroundWorker1;
Random ran;
long runningThreads = 0;
public void Start()
{
method();
// Console.WriteLine("Threads is finished");
}
private void method() // recursive method
{
Interlocked.Increment(ref runningThreads);
Console.WriteLine("New thread started");
Thread.Sleep(100);
backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.DoWork +=
new DoWorkEventHandler(backgroundWorker1_DoWork);
backgroundWorker1.RunWorkerAsync(); //Beginning new thread
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
ran = new Random();
Thread.Sleep(ran.Next(500, 1000));
if (ran.Next(1, 5) != 1) // if = 1 then to stop recursion
{
method();
}
Finished();
}
private void Finished()
{
Interlocked.Decrement(ref runningThreads);
if (Interlocked.Read(ref runningThreads) == 0)
{
Console.WriteLine("Threads is finished");
}
}