C# 如何在For循环中使用多线程
我想达到以下要求;请提出一些解决办法C# 如何在For循环中使用多线程,c#,.net,multithreading,.net-2.0,C#,.net,Multithreading,.net 2.0,我想达到以下要求;请提出一些解决办法 string[] filenames = Directory.GetFiles("C:\Temp"); //10 files for (int i = 0; i < filenames.count; i++) { ProcessFile(filenames[i]); //it takes time to execute } string[]filenames=Directory.GetFiles(“C:\Temp”)//10
string[] filenames = Directory.GetFiles("C:\Temp"); //10 files
for (int i = 0; i < filenames.count; i++)
{
ProcessFile(filenames[i]); //it takes time to execute
}
string[]filenames=Directory.GetFiles(“C:\Temp”)//10个文件
对于(int i=0;i
我想实现多线程。e、 g有10个文件。我想一次处理3个文件(可配置,比如说maxthreadcount
)。因此,3个文件将在for循环的3个线程中处理,如果任何线程完成了执行,它将从for循环中选择下一个项目。还希望确保在退出for循环之前处理所有文件
请推荐最佳方法。请看Joe Albahari的文章。它应该为你想要完成的事情提供一个良好的起点。试试看
Parallel.For(0, filenames.Length, i => {
ProcessFile(filenames[i]);
});
它只在.NET4之后才可用。希望可以接受。这将完成.net 2.0中的工作:
class Program
{
static int workingCounter = 0;
static int workingLimit = 10;
static int processedCounter = 0;
static void Main(string[] args)
{
string[] files = Directory.GetFiles("C:\\Temp");
int checkCount = files.Length;
foreach (string file in files)
{
//wait for free limit...
while (workingCounter >= workingLimit)
{
Thread.Sleep(100);
}
workingCounter += 1;
ParameterizedThreadStart pts = new ParameterizedThreadStart(ProcessFile);
Thread th = new Thread(pts);
th.Start(file);
}
//wait for all threads to complete...
while (processedCounter< checkCount)
{
Thread.Sleep(100);
}
Console.WriteLine("Work completed!");
}
static void ProcessFile(object file)
{
try
{
Console.WriteLine(DateTime.Now.ToString() + " recieved: " + file + " thread count is: " + workingCounter.ToString());
//make some sleep for demo...
Thread.Sleep(2000);
}
catch (Exception ex)
{
//handle your exception...
string exMsg = ex.Message;
}
finally
{
Interlocked.Decrement(ref workingCounter);
Interlocked.Increment(ref processedCounter);
}
}
}
类程序
{
静态int工作计数器=0;
静态int工作极限=10;
静态int processedCounter=0;
静态void Main(字符串[]参数)
{
string[]files=Directory.GetFiles(“C:\\Temp”);
int checkCount=files.Length;
foreach(文件中的字符串文件)
{
//等待自由限制。。。
while(工作计数器>=工作限制)
{
睡眠(100);
}
工作计数器+=1;
ParameterizedThreadStart pts=新的ParameterizedThreadStart(ProcessFile);
螺纹th=新螺纹(pts);
启动(文件);
}
//等待所有线程完成。。。
while(processedCounter
可以设置最大线程数取消并行选项
您可以使用
例如:
ThreadPool.SetMaxThreads(3, 3);
for (int i = 0; i < filenames.count; i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessFile), filenames[i]);
}
static void ProcessFile(object fileNameObj)
{
var fileName = (string)fileNameObj;
// do your processing here.
}
ThreadPool.SetMaxThreads(3,3);
对于(int i=0;i
如果您在应用程序的其他位置使用ThreadPool,那么这将不是一个好的解决方案,因为它是跨应用程序共享的
您还可以获取不同的线程池实现,例如,将文件名放入队列,然后启动三个线程来处理它们,而不是为每个文件名启动一个线程。或者,因为主线程现在是空闲的,所以启动两个线程,让主线程也在上面工作:
Queue<string> MyQueue;
void MyProc()
{
string[] filenames = Directory.GetFiles(...);
MyQueue = new Queue(filenames);
// start two threads
Thread t1 = new Thread((ThreadStart)ProcessQueue);
Thread t2 = new Thread((ThreadStart)ProcessQueue);
t1.Start();
t2.Start();
// main thread processes the queue, too!
ProcessQueue();
// wait for threads to complete
t1.Join();
t2.Join();
}
private object queueLock = new object();
void ProcessQueue()
{
while (true)
{
string s;
lock (queueLock)
{
if (MyQueue.Count == 0)
{
// queue is empty
return;
}
s = MyQueue.Dequeue();
}
ProcessFile(s);
}
}
Queue-MyQueue;
void MyProc()
{
string[]filename=Directory.GetFiles(…);
MyQueue=新队列(文件名);
//开始两个线程
线程t1=新线程((ThreadStart)ProcessQueue);
线程t2=新线程((ThreadStart)ProcessQueue);
t1.Start();
t2.Start();
//主线程也处理队列!
ProcessQueue();
//等待线程完成
t1.Join();
t2.连接();
}
private object queueLock=新对象();
void ProcessQueue()
{
while(true)
{
字符串s;
锁(队列锁)
{
如果(MyQueue.Count==0)
{
//队列为空
返回;
}
s=MyQueue.Dequeue();
}
进程文件;
}
}
另一个选项是使用信号量控制有多少线程正在工作:
Semaphore MySem = new Semaphore(3, 3);
void MyProc()
{
string[] filenames = Directory.GetFiles(...);
foreach (string s in filenames)
{
mySem.WaitOne();
ThreadPool.QueueUserWorkItem(ProcessFile, s);
}
// wait for all threads to finish
int count = 0;
while (count < 3)
{
mySem.WaitOne();
++count;
}
}
void ProcessFile(object state)
{
string fname = (string)state;
// do whatever
mySem.Release(); // release so another thread can start
}
Semaphore MySem=新信号量(3,3);
void MyProc()
{
string[]filename=Directory.GetFiles(…);
foreach(文件名中的字符串s)
{
mySem.WaitOne();
QueueUserWorkItem(进程文件,s);
}
//等待所有线程完成
整数计数=0;
而(计数<3)
{
mySem.WaitOne();
++计数;
}
}
无效进程文件(对象状态)
{
字符串fname=(字符串)状态;
//做任何事
mySem.Release();//释放,以便可以启动另一个线程
}
第一种方法的性能稍好一些,因为您不需要为每个处理的文件名启动和停止线程。但是,第二个线程更短、更干净,并且充分利用了线程池。您可能不会注意到性能上的差异。您真的被困在.NET 2.0上了吗?在.NET3.5或更好的4.0中会有更好的方法。@Joe:有没有使用线程池或信号量的建议?没有,除了:忘了它,除非你的处理是CPU密集型的。光盘的速度并没有神奇地加快。IO将是一个严重的瓶颈内容器。因为除非它做得很多,否则IO将是瓶颈。认真地你知道光盘与CPU内核相比有多慢吗?要平衡这一点需要大量的处理。@TomTom如果文件不需要一段时间读取,可能不会出现瓶颈。也许“执行需要时间”与加载文件后处理文件中的数据有关,在这种情况下,最好使用多线程。如果延迟是因为读取文件需要很长时间,那么我建议忘记多线程处理。举个时间损失的例子,在两个硬盘之间复制一个大文件,看看ETA,然后在上面复制第二个文件,看看ETA是如何增加一倍以上的!你真的只想读1fi
Semaphore MySem = new Semaphore(3, 3);
void MyProc()
{
string[] filenames = Directory.GetFiles(...);
foreach (string s in filenames)
{
mySem.WaitOne();
ThreadPool.QueueUserWorkItem(ProcessFile, s);
}
// wait for all threads to finish
int count = 0;
while (count < 3)
{
mySem.WaitOne();
++count;
}
}
void ProcessFile(object state)
{
string fname = (string)state;
// do whatever
mySem.Release(); // release so another thread can start
}