C#-单线程运行无限循环的多线程处理
我是多线程的新手(也是一个初学者/中级程序员),所以我可能遗漏了一些非常明显的东西。我目前正在开发一个应用程序,它必须从服务器(确切地说是彭博服务器)上提取数据,并运行业务逻辑 要从服务器上提取数据,基本上必须运行无止境的循环来不断刷新数据。目前,所有数据提取代码/逻辑都在一个单独的类中,并且有许多公共对象(下面代码中的dataDict)可以使用最新数据进行更新 我的想法是在一个单独的线程上运行程序的数据提取部分,并让其余的业务逻辑在主线程上运行。然后,只要业务逻辑需要最新的数据,它就可以从另一个线程(字典)调用数据对象。关于下面的代码,我希望该类在后台运行,并在需要时让主要业务逻辑选择字典Object>dataDict。但我真的不知道如何最好地做到这一点 我尝试使用BackgroundWorker,但我遇到的问题是,由于循环是无止境的,我永远无法启动RunWorkerCompleted事件处理程序,而且调用DoWork处理程序的时间太快(数据完全下载需要一段时间) 任何帮助都将不胜感激 为了说明程序的一部分,datapull的代码是(注意,我必须进行一些编辑,以便大括号/方括号可能不完美):C#-单线程运行无限循环的多线程处理,c#,multithreading,thread-safety,backgroundworker,C#,Multithreading,Thread Safety,Backgroundworker,我是多线程的新手(也是一个初学者/中级程序员),所以我可能遗漏了一些非常明显的东西。我目前正在开发一个应用程序,它必须从服务器(确切地说是彭博服务器)上提取数据,并运行业务逻辑 要从服务器上提取数据,基本上必须运行无止境的循环来不断刷新数据。目前,所有数据提取代码/逻辑都在一个单独的类中,并且有许多公共对象(下面代码中的dataDict)可以使用最新数据进行更新 我的想法是在一个单独的线程上运行程序的数据提取部分,并让其余的业务逻辑在主线程上运行。然后,只要业务逻辑需要最新的数据,它就可以从另一
类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);
}
}
}