Передача данных между потоками - PullRequest
0 голосов
/ 10 января 2011

У меня есть следующий код, в котором я пытаюсь обработать большой объем данных и обновить пользовательский интерфейс. Я пытался сделать то же самое, используя фоновый рабочий, но у меня возникла похожая проблема. Кажется, проблема в том, что я пытаюсь использовать класс, который не был создан в новом потоке (фактическая ошибка в том, что текущий поток не «владеет» экземпляром). У меня вопрос, есть ли способ, которым я могу передать этот экземпляр между потоками, чтобы избежать этой ошибки?

DataInterfaceClass dataInterfaceClass = new DataInterfaceClass();

private void OutputData(List<MyResult> Data)
{            
    progressBar1.Maximum = Data.Count;
    progressBar1.Minimum = 1;
    progressBar1.Value = 1;

    foreach (MyResult res in Data)
    {                       
        // Add data to listview
        UpdateStatus("Processing", res.Name);

        foreach (KeyValuePair<int, string> dets in res.Details)
        {
            ThreadPool.QueueUserWorkItem((o) =>
            {
                // Get large amount of data from DB based on key
                // – gives error because DataInterfaceClass was
                // created in different thread.
                MyResult tmpResult = dataInterfaceClass
                    .GetInfo(dets.DataKey);

                if (tmpResult == null)
                {
                    // Updates listview
                    UpdateStatus("Could not get details", 
                        dets.DataKey); 
                }
                else
                {
                    UpdateStatus("Got Details", dets.DataKey);
                }

                progressBar1.Dispatcher.BeginInvoke(
                    (Action)(() => progressBar1.Value++));
            });
        }
    }
}

EDIT:

DataInterfaceClass фактически определяется и создается вне функции, в которой он используется, но это экземпляр, а не статический.

Ответы [ 2 ]

1 голос
/ 10 января 2011

ОБНОВЛЕНИЕ : Вы, похоже, изменили опубликованный исходный код, поэтому ...

Вам следует создать экземпляр DataInterfaceClass исключительно для каждого фонового потока или задачи.Предоставьте своей задаче достаточное количество входных данных для создания собственного экземпляра.

При этом, если вы попытаетесь получить доступ к данным в одной базе данных с высокой степенью параллельности, это может привести к тайм-аутам базы данных.Даже если вы можете получить доступ к своим данным для многопоточной работы, я бы рекомендовал ограничить число одновременных фоновых задач, чтобы этого не происходило.

Вы можете использовать Semaphore(или аналогичный) для обеспечения одновременного выполнения не более определенного количества задач.

0 голосов
/ 10 января 2011

Создайте глобальный экземпляр для DataInterfaceClass внутри класса, для которого определен метод OutputData, чтобы вы могли использовать его внутри метода.

Однако вы должны быть осторожны при использовании. Если все потоки будут использовать один и тот же экземпляр для чтения из базы данных, это приведет к ошибкам.

Вы должны либо создать новый экземпляр DataInterfaceClass в каждом потоке, либо внедрить некоторую блокировку в свой метод GetInfo, чтобы избежать проблем множественного доступа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...