简体   繁体   English

使用ThreadPool.QueueUserWorkItem进行线程排序

[英]Ordering of thread using ThreadPool.QueueUserWorkItem

I'm new to threading basics. 我是线程基础的新手。

I have a queue of operations to be performed on a XML files(node add,node delete etc) 我有一个要在XML文件上执行的操作队列(节点添加,节点删除等)

1]There are 'n' xml files and for each file a thread from thread pool is allocated using ThreadPool.QueueUserWorkItem to do those file operations. 1]有'n'个xml文件,并且对于每个文件,使用ThreadPool.QueueUserWorkItem分配线程池中的线程来执行这些文件操作。

I want to achieve both concurrency and ordering of operation(important) using threads. 我想使用线程实现并发和操作(重要)的排序。
eg: Suppose if operations [a1,a2,a3,a4,a5] are to be performed on file "A.xml" 例如:假设是否要对文件“ A.xml”执行操作[a1,a2,a3,a4,a5]
and operations [b1,b2,b3,b4,b5,b6,b7] are to be performed on file "B.xml" ..... 和操作[b1,b2,b3,b4,b5,b6,b7]将在文件“ B.xml”上执行.....
I want to allocated threads such that i can perform these operations in the 我想分配线程,以便我可以在中执行这些操作
same order and also concurrently(since files are different). 顺序相同,并且并发(因为文件不同)。

2]Also is it possible to assign each operation a thread and achieve concurency and preserve order. 2]也可以为每个操作分配一个线程并实现并发性和保留顺序。

In STA model i did something similar.. 在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.
  }    
}

i want to do this concurrently with operation order preservation. 我想与操作订单保存同时进行。 Threads(of operation) can wait on one file...but Different operations take different execution times. (操作的)线程可以等待一个文件...但是不同的操作需要不同的执行时间。

i tried AutoResetEvent and WaitHandle.WaitAll(..) but it made the while loop stop untill all 'a(i)' operations finish..i want both a(i) and b(j) perform concurrently. 我尝试了AutoResetEvent和WaitHandle.WaitAll(..),但它使while循环停止,直到所有“ a(i)”操作完成。.我希望a(i)和b(j)同时执行。 (but ordering in a(i) and b(j)) (但按a(i)和b(j)排序)

Currently using .net 2.0 . 当前使用.net 2.0。

This is quite similar and is part of this question asked Question 这是很相似的,这是问题的一部分,问问题

Either create a new thread for each file, or just use one ThreadPool.QueueUserWorkItem call for each file - either way, you want the operations for the file to be executed sequentially in order, so there's no point in using multiple threads for that part. 为每个文件创建一个新线程,或者仅对每个文件使用一个 ThreadPool.QueueUserWorkItem调用-两种方式都希望顺序执行该文件的操作,因此对该部分使用多个线程没有意义。 In your case the only parallelism available is across different files, not operations. 在您的情况下,唯一可用的并行是跨不同文件,而不是跨操作。

You should avoid using thread blocking techniques like Monitor locks and WaitHandle structures in ThreadPool threads, since those threads are used by other processes. 您应该避免在ThreadPool线程中使用诸如Monitor锁和WaitHandle结构之类的线程阻塞技术,因为这些线程被其他进程使用。 You need to have your threading be based around individual files. 您需要使线程基于各个文件。 If an individual file doesn't take that long to process (and you don't have too many files), then the ThreadPool will work. 如果单个文件的处理时间不长(并且您没有太多文件),那么ThreadPool将起作用。

ThreadPool Implementation ThreadPool实现

You could just use EnqueueUserWorkItem on a file-centric method...something like this: 您可以在以文件为中心的方法上使用EnqueueUserWorkItem ...

private void ProcessFile(Object data)
{ 
    File f = (File)data;

    foreach(Operation oprn in getOperationsForFile(f))
    {
        performOperation(f, oprn);
    }
}

Then in your code that processes the files, do this: 然后在处理文件的代码中,执行以下操作:

while(queue.Count > 0)
{
    ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessFile), queue.Dequeue());
}

If you need your calling thread to block until they are all complete, then a WaitHandle is OK (since you're blocking your own thread, not the ThreadPool thread). 如果需要调用线程阻塞直到它们全部完成,则可以使用WaitHandle (因为您正在阻塞自己的线程, 而不是 ThreadPool线程)。 You will, however, have to create a small payload class to pass it to the thread: 但是,您将必须创建一个小的有效负载类以将其传递给线程:

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);

Thread Implementation 线程实现

If, however, you have a large number of files (or it may take a significant amount of time for your files to process), then creating your own threads is a better idea. 但是,如果您有大量文件(或者可能要花费大量时间来处理文件),那么创建自己的线程是一个更好的主意。 This also allows you to get away with omitting the WaitHandle s. 这也使您可以省略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();
}

The preceding example is a very rudimentary thread pool, but it should illustrate what needs to be done. 前面的示例是一个非常基本的线程池,但是它应该说明需要做什么。

Threads are for operations that can be done asynchronously and you want your operations done synchronously. 线程用于可以异步完成的操作,而您希望您的操作同步完成。 The processing of the files seems like they can be done asynchronously (multithreaded) though. 但是,文件的处理似乎可以异步(多线程)完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM