
[英]Using ThreadPool.QueueUserWorkItem - thread unexpectedly exits
[英]Ordering of thread using ThreadPool.QueueUserWorkItem
我是线程基础的新手。
我有一个要在XML文件上执行的操作队列(节点添加,节点删除等)
1]有'n'个xml文件,并且对于每个文件,使用ThreadPool.QueueUserWorkItem分配线程池中的线程来执行这些文件操作。
我想使用线程实现并发和操作(重要)的排序。
例如:假设是否要对文件“ A.xml”执行操作[a1,a2,a3,a4,a5]
和操作[b1,b2,b3,b4,b5,b6,b7]将在文件“ B.xml”上执行.....
我想分配线程,以便我可以在中执行这些操作
顺序相同,并且并发(因为文件不同)。
2]也可以为每个操作分配一个线程并实现并发性和保留顺序。
在STA模型中,我做了类似的事情。
while(queue.count>0){
File f = queue.Dequeue(); //get File from queue
OperationList oprlst = getOperationsForFile(f);
// will get list-> [a1,a2,a3,a4,a5]
for each Operation oprn in oprlst
{
performOperation(f,oprn)
//in MTA i want to wait till operation "a1" completes and then operation "a2" will
//start.making threads wait till file is in use or operation a(i) is in use.
}
}
我想与操作订单保存同时进行。 (操作的)线程可以等待一个文件...但是不同的操作需要不同的执行时间。
我尝试了AutoResetEvent和WaitHandle.WaitAll(..),但它使while循环停止,直到所有“ a(i)”操作完成。.我希望a(i)和b(j)同时执行。 (但按a(i)和b(j)排序)
当前使用.net 2.0。
这是很相似的,这是问题的一部分,问问题
为每个文件创建一个新线程,或者仅对每个文件使用一个 ThreadPool.QueueUserWorkItem
调用-两种方式都希望顺序执行该文件的操作,因此对该部分使用多个线程没有意义。 在您的情况下,唯一可用的并行是跨不同文件,而不是跨操作。
您应该避免在ThreadPool
线程中使用诸如Monitor
锁和WaitHandle
结构之类的线程阻塞技术,因为这些线程被其他进程使用。 您需要使线程基于各个文件。 如果单个文件的处理时间不长(并且您没有太多文件),那么ThreadPool
将起作用。
您可以在以文件为中心的方法上使用EnqueueUserWorkItem
...
private void ProcessFile(Object data)
{
File f = (File)data;
foreach(Operation oprn in getOperationsForFile(f))
{
performOperation(f, oprn);
}
}
然后在处理文件的代码中,执行以下操作:
while(queue.Count > 0)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessFile), queue.Dequeue());
}
如果需要调用线程阻塞直到它们全部完成,则可以使用WaitHandle
(因为您正在阻塞自己的线程, 而不是 ThreadPool
线程)。 但是,您将必须创建一个小的有效负载类以将其传递给线程:
private class Payload
{
public File File;
public AutoResetEvent Handle;
}
private void ProcessFile(Object data)
{
Payload p = (Payload)data;
foreach(Operation oprn in getOperationsForFile(p.File))
{
performOperation(f, oprn);
}
p.Handle.Set();
}
...
WaitHandle[] handles = new WaitHandle[queue.Count];
int index = 0;
while(queue.Count > 0)
{
handles[index] = new AutoResetEvent();
Payload p = new Payload();
p.File = queue.Dequeue();
p.Handle = handles[index];
ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessFile), p);
index++;
}
WaitHandle.WaitAll(handles);
但是,如果您有大量文件(或者可能要花费大量时间来处理文件),那么创建自己的线程是一个更好的主意。 这也使您可以省略WaitHandle
。
private void ProcessFile(File f)
{
foreach(Operation oprn in getOperationsForFile(f))
{
performOperation(f, oprn);
}
p.Handle.Set();
}
private object queueLock = new object();
private void ThreadProc()
{
bool okToContinue = true;
while(okToContinue)
{
File f = null;
lock(queueLock)
{
if(queue.Count > 0)
{
f = queue.Dequeue();
}
else
{
f = null;
}
}
if(f != null)
{
ProcessFile(f);
}
else
{
okToContinue = false;
}
}
}
...
Thread[] threads = new Thread[20]; // arbitrary number, choose the size that works
for(int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(new ThreadStart(ThreadProc));
thread[i].Start();
}
//if you need to wait for them to complete, then use the following loop:
for(int i = 0; i < threads.Length; i++)
{
threads[i].Join();
}
前面的示例是一个非常基本的线程池,但是它应该说明需要做什么。
线程用于可以异步完成的操作,而您希望您的操作同步完成。 但是,文件的处理似乎可以异步(多线程)完成。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.