C # - многопоточность с одним потоком работает бесконечный цикл - PullRequest
1 голос
/ 30 декабря 2010

Я новичок в многопоточности (и несколько начинающий / средний программист), и поэтому я могу упустить что-то очень очевидное. В настоящее время я работаю над приложением, которое должно извлекать данные с сервера (точнее, с сервера Bloomberg), а также запускать бизнес-логику.

Чтобы извлечь данные с сервера, вам необходимо выполнить бесконечный цикл, чтобы постоянно обновлять данные. В настоящее время весь код / ​​логика извлечения данных находится в одном отдельном классе и имеет ряд открытых объектов (dataDict в коде ниже), которые обновляются с использованием новейших данных.

Я думал о том, чтобы запустить часть программы для извлечения данных в отдельном потоке, а остальную часть бизнес-логики запустить в главном потоке. Затем, когда бизнес-логике требуются самые последние данные, она может просто вызывать объект данных из другого потока (словарь). Что касается приведенного ниже кода, я бы хотел, чтобы этот класс работал в фоновом режиме и чтобы основная бизнес-логика выбирала Dictionary, Object> dataDict, когда это необходимо. Я действительно не уверен, как лучше всего сделать это все же.

Я пытался использовать BackgroundWorker, но проблема, с которой я столкнулся, заключалась в том, что, поскольку цикл был бесконечным, я никогда не мог запустить обработчик события RunWorkerCompleted, а обработчик DoWork вызывался бы слишком рано (для передачи данных требуется некоторое время) полностью скачать).

Любая помощь будет высоко ценится!

Чтобы проиллюстрировать часть программы, код для datapull выглядит следующим образом (обратите внимание, мне пришлось немного отредактировать, чтобы скобки / скобки не были идеальными):

class BloombergSync
{
    private Session mainSession = new Session();
    private List<String> contracts = new List<string>();
    private List<String> fields = new List<string>();
    public List<String> safeContracts = new List<string>();
    public List<String> safeFields = new List<string>();
    public Dictionary<Tuple<string, string>, Object> dataDict = new Dictionary<Tuple<string, string>, object>();
    private BackgroundWorker worker = new BackgroundWorker();


    {

        while (true)
        {

            try
            {
                Event eventObj = mainSession.NextEvent();

                foreach (Message msg in eventObj.GetMessages())
                {
                    if (eventObj.Type == Event.EventType.SUBSCRIPTION_DATA)
                    {
                        Element dataElement = msg.AsElement;

                        //Figures out which contract the data is in reference to.
                        string topic = msg.TopicName;

                        // Then must add the data to the appropriate contract and field. 
                        foreach (string field in fields)
                        {
                            if (dataElement.HasElement(field, true))
                            {
                                // Collects data for the field
                                Element elm = dataElement.GetElement(field);
                                var dataPoint = elm.GetValue();

                                // Have to figure out how to select first topic, and then the field within that topic. Has
                                // two keys (first topic, then field).
                                Tuple<string, string> tuple = new Tuple<string, string>(topic, field);
                                dataDict[tuple] = dataPoint;
                                worker.ReportProgress(1);
                            }

                        }

                     }
                    else
                    {
                        //Do Nothing if not data
                    }
                }
            }
            catch (Exception ex)
            {
                System.Console.WriteLine("Got Exception:" + ex);
            }

        }
    }

1 Ответ

7 голосов
/ 30 декабря 2010

Звучит как сценарий producer-consumer.Вам необходим объект thread-safe (в вашем случае очередь) для передачи данных.

В .NET 4.0 есть System.Collections.Concurrent, равный thread-safe, и вы можете использовать его в своем проекте.Затем ваш фоновый работник может поместить данные в CuncurrentQueue, а потребитель (и) могут удалить из очереди элементы данных.

...