我正在通过第一次尝试线程化应用程序。该应用程序适用于大型数据集,该数据集被分成存储在磁盘上的可管理块,因此整个数据集永远不需要一次驻留在内存中。相反,数据的一个子集可以根据需要逐块加载。这些块先前在主线程中被一个接一个地加载。当然,这将有效地暂停所有GUI和其他操作,直到数据完全加载。线程池 - 如何从工作线程调用主线程中的方法(使用参数)
所以我决定研究线程,并在应用程序继续正常工作时进行加载。我通过沿下方的伪码的线路做一些事来报复的基本概念与线程池的工作:
public class MyApp
{
List<int> listOfIndiciesToBeLoaded; //This list gets updated based on user input
Dictionary<int,Stuff> loadedStuff = new Dictionary<int,Stuff>();
//The main thread queues items to be loaded by the ThreadPool
void QueueUpLoads()
{
foreach(int index in listOfIndiciesToBeLoaded)
{
if(!loadedStuff.ContainsKey(index))
loadedStuff.Add(index,new Stuff());
LoadInfo loadInfo = new LoadInfo(index);
ThreadPool.QueueUserWorkItem(LoadStuff, loadInfo);
}
}
//LoadStuff is called from the worker threads
public void LoadStuff(System.Object loadInfoObject)
{
LoadInfo loadInfo = loadInfoObject as LoadInfo;
int index = loadInfo.index;
int[] loadedValues = LoadValuesAtIndex(index); /* here I do my loading and ...*/
//Then I put the loaded data in the corresponding entry in the dictionary
loadedStuff[index].values = loadedValues;
//Now it is accessible from the main thread and it is flagged as loaded
loadedStuff[index].loaded = true;
}
}
public class Stuff
{
//As an example lets say the data being loaded is an array of ints
int[] values;
bool loaded = false;
}
//a class derived from System.Object to be passed via ThreadPool.QueueUserWorkItem
public class LoadInfo : System.Object
{
public int index;
public LoadInfo(int index)
{
this.index = index;
}
}
相比相当复杂的例子,我已经遇到,当设法这是很原始在过去的几天里学习这些东西。当然,它会同时加载数据并将其填充到可从主线程访问的字典中,但这也会给我带来一个至关重要的问题。我需要在加载项目时通知主线程,以及它是哪个项目以便可以处理和显示新数据。理想情况下,我希望每个完成的负载在主线程上调用一个函数,并为其提供索引和新加载的数据作为参数。我明白,我不能只从多个其他线程同时运行的主线程调用函数。他们必须以某种方式排队等待主线程在没有做其他事情时运行它们。但这是我目前对线程通信的理解脱落的地方。
我已经阅读了几个关于如何使用Control.Invoke(委托)设置事件和委托时使用Windows窗体的深入解释。但是我没有使用Windows窗体,也没有能够应用这些想法。我想我需要一个更通用的方法,不依赖于Control类。如果你确实做出了回应,请详细说明,也许在我的伪代码中使用一些命名。这样我就会更容易跟随。线程似乎是一个相当深刻的话题,我只是要掌握基本知识。请随时就如何改进我的问题提出建议,使其更加清晰。
为什么'loadInfoObject as pv_LoadInfo'? –
我的不好 - 编辑修复 – absentia
如果你使用.NET FW 4.5,你可能想看看'await' /'async'。此外,您的代码不是线程安全的 - “字典”不*线程安全 - 如果您需要共享该字典,请改用'ConcurrentDictionary '。 *您使用的是什么GUI?WPF也有Invoke(请看'Dispatcher')。如果你的“GUI”是一个控制台,它会变得棘手,你需要在你的主循环中加入一个消息队列(可能是'ConcurrentQueue ')并定期检查它 - 如果它有数据,则立即出队并处理它。 –
Luaan