Как лучше всего передавать данные между параллельными потоками в .NET?

StackOverflow https://stackoverflow.com/questions/106979

Вопрос

У меня есть два потока, один нужно опросить кучу отдельных статических ресурсов в поисках обновлений.Другой должен получить данные и сохранить их в базе данных.Как поток 1 может сообщить потоку 2, что есть что-то для обработки?

Это было полезно?

Решение

Если фрагменты данных независимы, рассматривайте их как рабочие элементы, которые будут обрабатываться пулом потоков.Используйте пул потоков и QueueUserWorkItem для публикации данных в теме(ях).Вы должны добиться лучшей масштабируемости, используя пул симметричных потоков и ограничивая объем синхронизации, которая должна происходить между производителем и потребителем(ями).

Например (из 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); 
}

Другие советы

Я использую Monitor.Wait/Pulse в очереди рабочих элементов.

Всегда ли должен быть запущен поток «хранить в БД»?Похоже, что лучшим вариантом (если это возможно) было бы заставить поток опроса запустить другой поток для сохранения.Однако в зависимости от количества создаваемых потоков может оказаться, что использование первого потока опроса ThreadPool.QueueUserWorkItem() может быть более эффективным маршрутом.

Для большей эффективности при сохранении в базе данных я бы использовал асинхронный ввод-вывод в БД, а не методы синхронизации.

В любой момент, когда вы можете избежать необходимости прямого взаимодействия между двумя потоками, вам следует это сделать.Из-за необходимости собрать воедино некоторые примитивы синхронизации ваш код будет не так легко отлаживать, и он может привести к появлению некоторых очень тонких условий гонки, которые вызывают ошибки типа «выполнение один раз на миллион» (находить/исправлять которые далеко не весело).

Если второй поток всегда должен выполняться, сообщите нам, почему, предоставив дополнительную информацию, и мы сможем дать более подробный ответ.

Удачи!

Лично я бы хотел, чтобы поток 1 вызывал события, на которые мог бы ответить поток 2.Потоки могут быть связаны с соответствующими событиями управляющим процессом, который инициирует оба потока.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top