在.NET中并发线程之间传递数据的最佳方法是什么?

时间:2021-04-20 20:58:18

I have two threads, one needs to poll a bunch of separate static resources looking for updates. The other one needs to get the data and store it in the database. How can thread 1 tell thread 2 that there is something to process?

我有两个线程,一个需要轮询一堆独立的静态资源来寻找更新。另一个需要获取数据并将其存储在数据库中。线程1如何告诉线程2有什么要处理的?

4 个解决方案

#1


7  

If the pieces of data are independant then treat the pieces of data as work items to be processed by a pool of threads. Use the thread pool and QueueUserWorkItem to post the data to the thread(s). You should get better scalability using a pool of symmetric threads and limiting the amount of synchronisation that has to occur between the producer and consumer(s).

如果数据片段是独立的,则将数据片段视为要由线程池处理的工作项。使用线程池和QueueUserWorkItem将数据发布到线程。您应该使用对称线程池获得更好的可伸缩性,并限制生产者和消费者之间必须发生的同步量。

For example (from MSDN):

例如(来自MSDN):

    TaskInfo ti = new TaskInfo("This report displays the number {0}.", 42);

    // Queue the task and data.
    if (ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc), ti)) {    
        Console.WriteLine("Main thread does some work, then sleeps.");

        // If you comment out the Sleep, the main thread exits before
        // the ThreadPool task has a chance to run.  ThreadPool uses 
        // background threads, which do not keep the application 
        // running.  (This is a simple example of a race condition.)
        Thread.Sleep(1000);

        Console.WriteLine("Main thread exits.");
    }
    else {
        Console.WriteLine("Unable to queue ThreadPool request."); 
    }


// The thread procedure performs the independent task, in this case
// formatting and printing a very simple report.
//
static void ThreadProc(Object stateInfo) {
    TaskInfo ti = (TaskInfo) stateInfo;
    Console.WriteLine(ti.Boilerplate, ti.Value); 
}

#2


5  

I use Monitor.Wait / Pulse on a Queue of work items.

我在工作项的队列上使用Monitor.Wait / Pulse。

#3


0  

Does the "store in the DB" thread always need to be running? It seems like perhaps the best option (if possible) would be to have the polling thread spin up another thread to do the save. Depending on the number of threads being created though, it could be that having the first polling thread use ThreadPool.QueueUserWorkItem() might be the more efficient route.

“DB中的存储”线程是否总是需要运行?似乎最好的选择(如果可能的话)是让轮询线程旋转另一个线程来进行保存。根据创建的线程数,可能是第一个轮询线程使用ThreadPool.QueueUserWorkItem()可能是更有效的路由。

For more efficiency, when saving to the database, I would use async I/O on the DB rather than the sync methods.

为了提高效率,在保存到数据库时,我会在数据库上使用异步I / O而不是同步方法。

Anytime you can get away from having to communicate directly between two threads, you should. Having to throw together some sync primitives, your code won't be as easy to debug and could introduce some very subtle race conditions that cause "once in a million execution" type bugs (which are far from fun to find/fix).

任何时候你都可以摆脱两个线程之间的直接通信,你应该这样做。必须将一些同步原语放在一起,你的代码将不会那么容易调试,并且可能会引入一些非常微妙的竞争条件,导致“一百万次执行”类型的错误(找到/修复它们很有趣)。

If the second thread always needs to be executing, let us know why with some more information and we can come back with a more in-depth answer.

如果第二个线程总是需要执行,请告诉我们为什么有更多信息,我们可以回过头来获得更深入的答案。

Good luck!

#4


0  

I personally would have thread 1 raise events which thread 2 can respond to. The threads can be wired up to the appropriate events by the controlling process which initiates both the threads.

我个人会有线程1引发线程2可以响应的事件。线程可以通过控制进程连接到适当的事件,该控制进程启动两个线程。

#1


7  

If the pieces of data are independant then treat the pieces of data as work items to be processed by a pool of threads. Use the thread pool and QueueUserWorkItem to post the data to the thread(s). You should get better scalability using a pool of symmetric threads and limiting the amount of synchronisation that has to occur between the producer and consumer(s).

如果数据片段是独立的,则将数据片段视为要由线程池处理的工作项。使用线程池和QueueUserWorkItem将数据发布到线程。您应该使用对称线程池获得更好的可伸缩性,并限制生产者和消费者之间必须发生的同步量。

For example (from MSDN):

例如(来自MSDN):

    TaskInfo ti = new TaskInfo("This report displays the number {0}.", 42);

    // Queue the task and data.
    if (ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc), ti)) {    
        Console.WriteLine("Main thread does some work, then sleeps.");

        // If you comment out the Sleep, the main thread exits before
        // the ThreadPool task has a chance to run.  ThreadPool uses 
        // background threads, which do not keep the application 
        // running.  (This is a simple example of a race condition.)
        Thread.Sleep(1000);

        Console.WriteLine("Main thread exits.");
    }
    else {
        Console.WriteLine("Unable to queue ThreadPool request."); 
    }


// The thread procedure performs the independent task, in this case
// formatting and printing a very simple report.
//
static void ThreadProc(Object stateInfo) {
    TaskInfo ti = (TaskInfo) stateInfo;
    Console.WriteLine(ti.Boilerplate, ti.Value); 
}

#2


5  

I use Monitor.Wait / Pulse on a Queue of work items.

我在工作项的队列上使用Monitor.Wait / Pulse。

#3


0  

Does the "store in the DB" thread always need to be running? It seems like perhaps the best option (if possible) would be to have the polling thread spin up another thread to do the save. Depending on the number of threads being created though, it could be that having the first polling thread use ThreadPool.QueueUserWorkItem() might be the more efficient route.

“DB中的存储”线程是否总是需要运行?似乎最好的选择(如果可能的话)是让轮询线程旋转另一个线程来进行保存。根据创建的线程数,可能是第一个轮询线程使用ThreadPool.QueueUserWorkItem()可能是更有效的路由。

For more efficiency, when saving to the database, I would use async I/O on the DB rather than the sync methods.

为了提高效率,在保存到数据库时,我会在数据库上使用异步I / O而不是同步方法。

Anytime you can get away from having to communicate directly between two threads, you should. Having to throw together some sync primitives, your code won't be as easy to debug and could introduce some very subtle race conditions that cause "once in a million execution" type bugs (which are far from fun to find/fix).

任何时候你都可以摆脱两个线程之间的直接通信,你应该这样做。必须将一些同步原语放在一起,你的代码将不会那么容易调试,并且可能会引入一些非常微妙的竞争条件,导致“一百万次执行”类型的错误(找到/修复它们很有趣)。

If the second thread always needs to be executing, let us know why with some more information and we can come back with a more in-depth answer.

如果第二个线程总是需要执行,请告诉我们为什么有更多信息,我们可以回过头来获得更深入的答案。

Good luck!

#4


0  

I personally would have thread 1 raise events which thread 2 can respond to. The threads can be wired up to the appropriate events by the controlling process which initiates both the threads.

我个人会有线程1引发线程2可以响应的事件。线程可以通过控制进程连接到适当的事件,该控制进程启动两个线程。