C#-单线程运行无限循环的多线程处理

C#-单线程运行无限循环的多线程处理,c#,multithreading,thread-safety,backgroundworker,C#,Multithreading,Thread Safety,Backgroundworker,我是多线程的新手(也是一个初学者/中级程序员),所以我可能遗漏了一些非常明显的东西。我目前正在开发一个应用程序,它必须从服务器(确切地说是彭博服务器)上提取数据,并运行业务逻辑 要从服务器上提取数据,基本上必须运行无止境的循环来不断刷新数据。目前,所有数据提取代码/逻辑都在一个单独的类中,并且有许多公共对象(下面代码中的dataDict)可以使用最新数据进行更新 我的想法是在一个单独的线程上运行程序的数据提取部分,并让其余的业务逻辑在主线程上运行。然后,只要业务逻辑需要最新的数据,它就可以从另一

我是多线程的新手(也是一个初学者/中级程序员),所以我可能遗漏了一些非常明显的东西。我目前正在开发一个应用程序,它必须从服务器(确切地说是彭博服务器)上提取数据,并运行业务逻辑

要从服务器上提取数据,基本上必须运行无止境的循环来不断刷新数据。目前,所有数据提取代码/逻辑都在一个单独的类中,并且有许多公共对象(下面代码中的dataDict)可以使用最新数据进行更新

我的想法是在一个单独的线程上运行程序的数据提取部分,并让其余的业务逻辑在主线程上运行。然后,只要业务逻辑需要最新的数据,它就可以从另一个线程(字典)调用数据对象。关于下面的代码,我希望该类在后台运行,并在需要时让主要业务逻辑选择字典Object>dataDict。但我真的不知道如何最好地做到这一点

我尝试使用BackgroundWorker,但我遇到的问题是,由于循环是无止境的,我永远无法启动RunWorkerCompleted事件处理程序,而且调用DoWork处理程序的时间太快(数据完全下载需要一段时间)

任何帮助都将不胜感激

为了说明程序的一部分,datapull的代码是(注意,我必须进行一些编辑,以便大括号/方括号可能不完美):

类BloombergSync
{
私有会话mainSession=新会话();
私有列表合同=新列表();
私有列表字段=新列表();
public List safeContracts=新列表();
public List safeFields=新列表();
公共字典dataDict=新字典();
私有BackgroundWorker worker=新BackgroundWorker();
{
while(true)
{
尝试
{
Event eventObj=mainSession.NextEvent();
foreach(eventObj.GetMessages()中的消息msg)
{
if(eventObj.Type==Event.EventType.SUBSCRIPTION\u数据)
{
元素dataElement=msg.AsElement;
//找出数据所参照的合同。
字符串topic=msg.TopicName;
//然后必须将数据添加到相应的合同和字段中。
foreach(字段中的字符串字段)
{
if(dataElement.HasElement(字段,true))
{
//为字段收集数据
Element elm=dataElement.GetElement(字段);
var dataPoint=elm.GetValue();
//必须弄清楚如何选择第一个主题,然后选择该主题中的字段
//两个键(第一个主题,然后是字段)。
Tuple Tuple=新的Tuple(主题、字段);
dataDict[tuple]=数据点;
工人进度报告(1);
}
}
}
其他的
{
//如果没有数据,什么也不做
}
}
}
捕获(例外情况除外)
{
System.Console.WriteLine(“得到异常:+ex”);
}
}
}

听起来像是一个
生产者-消费者
场景。您需要一个
线程安全的
对象(在您的例子中是一个队列)来传输数据


.NET 4.0
中有一个
系统.Collections.Concurrent
,它是
线程安全的
,您可以在项目中使用。然后,您的后台工作人员可以将数据放入
CuncurrentQueue
和使用者中可以将数据项出列。

听起来像是一个
生产者-消费者
场景。您需要一个
线程安全的
对象(在您的示例中是队列)来传输数据


.NET 4.0
中有一个
系统.Collections.Concurrent
,它是
线程安全的
,您可以在项目中使用。然后,您的后台工作人员可以将数据放入
CuncurrentQueue
和使用者中可以将数据项出列。

我只是在看这个问题,并认为这可能是解决方法。我还发现,如果我使用BackgroundWorker,我可以使用ProgressChanged事件,并使用ReportProgress的重载方法将一个对象传递回事件处理程序。我发送回的对象是我为发送三个字段而构建的类ds我想要…不确定这是否是最有效的,但它看起来像是在工作。线程类型在第一步不是您的设计问题。设计共享数据模型,以及如何安全地访问它们
线程
。然后您需要分叉执行路径,以便主线程执行某些操作,而另一个线程将生成数据。主线程(使用共享数据对象)可以提取数据(如果可用)并使用它。如果队列已满,最好阻止生产者线程。最后一件事你应该注意的是,你是否需要一个正常的线程或背景,这取决于你的情况。例如,没有数据,主应用程序无事可做,那么背景工作者不是一个好主意。我只是在看这一点,并认为这可能是解决问题的方法go。我还发现,如果我使用BackgroundWorker,我可以使用ProgressChanged事件,并使用ReportProgress的重载方法将一个对象传递回事件处理程序。我发送回的对象是我创建的一个类,用于发送我想要的三个字段……不确定这是否是最有效的,但它看起来像是在工作。类型线程不是第一步的设计问题
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);
            }

        }
    }