我有一个c#控制台应用程序,最多可以创建5个线程。
线程执行正常,但UI线程在完成工作时关闭。
有没有办法让主UI线程保持运行,只要副线程正在运行?
foreach (var url in urls)
{
Console.WriteLine("starting thread: " + url);
ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(myMethod), url);
}
我按照上面的代码开始我的线程。
答案 0 :(得分:9)
ThreadPool中的线程是后台线程,这意味着现有的应用程序不会等待它们完成。
您有几个选择:
Parallel.ForEach(urls, url => MyMethod(url));
答案 1 :(得分:7)
如果您使用的是.NET 4.0:
var tasks = new List<Task>();
foreach(var url in urls)
{
tasks.Add(Task.Factory.StartNew(myMethod, url));
}
// do other stuff...
// On shutdown, give yourself X number of seconds to wait for them to complete...
Task.WaitAll(tasks.ToArray(), TimeSpan.FromSeconds(30));
答案 2 :(得分:2)
啊 - ThreadPool是后台。它已排队,但随后您的程序结束。成品。程序终止。
读取信号量(WaitSignal)并等待 - 结束时回调中的线程信号结束,当所有信号都表明主线程可以继续时。
答案 3 :(得分:1)
如果你正在使用.net 4,那么:
urls.AsParallel().ForAll(MyMethod);
在.net 4之前,然后启动单个线程,将它们保存在列表中并调用Join()。工作人员不是背景的事实会在主线程退出后保持活着,但Join()更明确。
List<Thread> workers = new List<Thread>();
foreach(var url in urls)
{
Thread t = new Thread(MyMethod) {IsBackground = false};
workers.Add(t);
t.Start(url);
}
foreach (var worker in workers)
{
worker.Join();
}
答案 4 :(得分:0)
最简单的解决问题的方法。
在您的课程班中:
static volatile int ThreadsComplete = 0;
在返回结束时的“myMethod”中:
//ThreadsComplete++; //*edit* for safety's sake
Interlocked.Increment(ref ThreadsComplete);
在你的main方法返回/结束之前:
while(ThreadsComplete < urls.Count) { Thread.Sleep(10); }
以上基本上是一个WaitForAll同步方法。
答案 5 :(得分:-1)
:
var m = new ManualResetEvent(false);
// do something
foreach (var url in urls)
{
Console.WriteLine("starting thread: " + url);
ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(myMethod), url);
}
m.WaitOne();
private static void myMethod(object obj)
{
try{
// do smt
}
finally {
m.Set();
}
}