我正在尝试在c#中实现多线程。
基本理念是:
会有很多线程进程调用一个函数,并且每个线程都不会被调用。
我想限制最大线程数。
线程完成后,我想调用另一个线程,直到完成所有操作。
为了实现这一点,我使用了一个线程列表。对于每一秒,我检查列表是否已满,以及是否有任何线程完成其工作。
这是我的代码:
List<Thread> threadCompany = new List<Thread>();
List<Thread> fireThisGuy = new List<Thread>();
while (i < _finish) {
if (threadCompany.Count < _MAX_THREAD) {
Thread worker = new Thread(delegate() {
CallFunction(i);
});
threadCompany.Add(worker);
i++;
worker.Start();
}
Thread.Sleep(1000); //Wait for a while instead of keep calling if
foreach (Thread worker in threadCompany) {
if (!worker.IsAlive) {
fireThisGuy.Add(worker); //because threadCompany may not be
//modified in iteration.
}
}
foreach (Thread worker in fireThisGuy) {
threadCompany.Remove(worker);
}
fireThisGuy.Clear();
}
这样可行,但我认为我在这里不优雅高效,如何改进我的代码呢?
答案 0 :(得分:5)
这不是解决问题的正确方法。 您不需要保留线程列表,只需在所有线程完成运行时通知应用程序。
这是一种处理问题的可能方法,使用SynchronizationContext在执行完成时通知主线程,没有任何等待周期。
public class OwnerClass
{
private SynchronizationContext syncContext;
private int count;
private int completedCount;
// This event will be raised when all thread completes
public event EventHandler Completed;
public OwnerClass() :
this(SynchronizationContext.Current)
{
}
public OwnerClass(SynchronizationContext context)
{
if (context == null)
throw new ArgumentNullException("context");
this.syncContext = context;
}
// Call this method to start running
public void Run(int threadsCount)
{
this.count = threadsCount;
for (int i = 0; i < threadsCount; ++i)
{
ThreadPool.QueueUserWorkItem(this.ThreadFunc, null);
}
}
private void ThreadFunc(object threadContext)
{
Thread.Sleep(1000); /// my long and complicated function
if (Interlocked.Increment(ref this.completedCount) >= this.count)
{
this.syncContext.Post(OnCompleted, null);
}
}
protected virtual void OnCompleted(object state)
{
var handler = this.Completed;
if (handler != null)
handler(this, EventArgs.Empty);
}
}
如果您只是想在多处理器中运行,为每个处理器分配一个线程,您只需使用Parallel.For
答案 1 :(得分:4)
结帐TPL和/或ThreadPool。