C# WinApp窗体在加载事件期间加载太多数据
我有一个表单正在从SQLServer加载大量数据。下面的代码将提供一个很好的提示:C# WinApp窗体在加载事件期间加载太多数据,c#,winforms,backgroundworker,C#,Winforms,Backgroundworker,我有一个表单正在从SQLServer加载大量数据。下面的代码将提供一个很好的提示: private void BranchCenter_Load(object sender, EventArgs e) { //Combo boxes: LoadCities(); LoadCoordinators(); LoadComputerSystems(); //Actual entity LoadBranch(); } private void LoadCities() {
private void BranchCenter_Load(object sender, EventArgs e) {
//Combo boxes:
LoadCities();
LoadCoordinators();
LoadComputerSystems();
//Actual entity
LoadBranch();
}
private void LoadCities() {
//LINQ2SQL to load data. ~5000 records.
}
private void LoadCoordinators() {
//LINQ2SQL to load data. ~50 records.
}
private void LoadComputerSystems() {
//LINQ2SQL to load data. ~550 records.
}
private void LoadBranch() {
LoadBranchInit();
LoadBranchDetails();
LoadBranchTimings();
LoadBranchServices();
LoadBranchLocumsHistory();
LoadBranchJobs();
LoadBranchNotes();
}
private void LoadBranchInit() {
//LINQ2SQL to load the Branch object based upon the Branch ID
}
private void LoadBranchDetails() {
//LINQ2SQL to load basic branch stuff. 38 fields. Mixed editors.
}
private void LoadBranchTimings() {
//LINQ2SQL to load timings info into 80 date-time controls
}
private void LoadBranchServices() {
//LINQ2SQL to load services offered at branch info into 20 check-boxes controls
}
private void LoadBranchLocumsHistory() {
//LINQ2SQL to load branch history info into grid control. Always increasing # of rows :(
}
private void LoadBranchJobs() {
//LINQ2SQL to load branch jobs info into grid control. Always increasing # of rows :(
}
private void LoadBranchNotes() {
//LINQ2SQL to load branch notes info into grid control
}
UI是一个带有选项卡控件的表单。上面的每个细节都会进入一个选项卡页面。我需要加载和显示的形式给用户尽快。一旦表单显示出来,我需要启动一系列后台工作程序来获取每个页面的数据
我一直试图搞乱后台工作人员,但无法理解它的用法。最后,我收到了这样一条消息:“不同的线程试图访问主线程上的控制权…或者类似的东西…”
理想的情况是在每个选项卡上都有一个加载数据的进度条,并且在相应的后台工作人员完成后,该选项卡就可以交互
有什么策略或建议吗?感谢阅读。如果每种类型的数据仅显示在一个页面上,我会移动代码,以便在第一次加载每个选项卡页面时加载每种相应类型的数据。这样,数据加载工作将在更长的时间内分配,如果用户在会话期间没有导航到所有选项卡,则可能完全避免
加载页面时,可以使用
BackgroundWorker
或任何其他异步机制。在选项卡页面中,可以有两个面板控件。一个包含页面的UI,并且在加载表单时具有Visible=false
,另一个包含带有文本“Loading,please wait…”的标签。为页面加载数据并更新UI时,在两个面板上切换可见性以显示UI。这样,表单在加载数据时仍然会有响应,而且由于一次只加载一页数据,加载时间应该相当短 这里的问题是BackgroundWorker的DoWork方法无法接触GUI
它必须使用BackgroundWorker.ReportProgress(int-progress,object-state)
在GUI线程上调用一个可以自由更新GUI的方法
这里最重要的一点是,GUI控件只能从GUI线程本身更新,否则程序中会到处出现随机异常。理想的解决方案是不在表单加载事件中加载数据 让表单正确、完整地加载,以便UI呈现完成 之后,您可以在任何需要的地方显示进度条,并且可以执行实际的数据加载(同步或异步)
如果你不需要同时加载所有的东西,我也会考虑只在第一次访问标签时加载数据,所以如果用户从来没有点击最后一个标签,例如,你没有为它加载任何东西。
你不能从UI线程之外的任何其他线程中使用UI。这就是你错误的根源。如果您想了解有关如何从不同线程正确更新UI元素的更多信息,则需要使用Invoke。关于堆栈溢出的问题可能会帮助您解决。为了解决后台工作线程遇到的问题,听起来您可能试图从线程本身访问UI组件。要从非UI线程执行此操作,您需要使用Control.Invoke,而不是尝试直接访问组件。是的,BackgroundWorker非常适合这样做 我认为你做得不对,因为你想在嫁妆活动中改变你的形式 但是,您应该只在e中收集此事件的结果。该事件的结果然后在RunWorkerCompleted中,您可以使用其e.Results更改表单。为每个选项卡创建一个BackgroundWorker。在窗体的加载事件中,禁用所有选项卡,并为每个后台工作进程调用RunWorkerAsync()方法 在每个DoWork事件处理程序中,将关联选项卡页所需的数据从数据库加载到数据表中,并将DoWorkEventArgs的Result属性设置为数据表 注意:在DoWork事件处理程序中,您不应该更新任何UI控件,因为它在不同的线程中运行。您应该只从数据库中检索数据并设置Result属性
在RunWorkerCompletedEventHandler中,您可以通过获取RunWorkerCompletedEventArgs的Result属性来访问在DoWork事件处理程序中检索的数据表。然后,您可以相应地设置UI控件的属性,然后启用与当前后台工作程序关联的选项卡页。好的。在很短的时间内做出了巨大的反应。我喜欢这个地方。从二环跳下,我与他面对面。这也是一个好的替代品吗?找不到关于如何在我的场景中使用Rx的教程。TabControl已经进行了延迟加载
帮你自己一个忙,把每个标签的内容放在一个用户控件上。好的,我面临一个新的情况。我转到VisualStudio2010,遇到Task.Factory.StartNew(()=>myMethod()) 这就是我到目前为止所做的:
private void LoadLocum() {
var TaskInit = Task.Factory.StartNew(() => LoadLocumInit());
TaskInit.Wait();
var TaskDetails = Task.Factory.StartNew(() => LoadLocumDetails());
TaskDetails.Wait();
var TaskQualifications = Task.Factory.StartNew(() => LoadLocumQualifications());
//Enable Qualification TabPage automatically whenever TaskQualifications is complete
Parallel.Invoke(
() => LoadLocumComputerSystems(),
() => LoadLocumOtherInfo(),
() => LoadLocumEmergencyContacts(),
() => LoadLocumDistanceRates(),
() => LoadLocumDocuments(),
() => LoadLocumNotes(),
() => LoadLocumBannedStatus()
);
}
前两个步骤(任务)至关重要。现在,选项卡的选项卡页被禁用。我需要在完成相关任务的基础上启用它们。我可以找到一个要订阅的事件,表明某项任务是否完成。数据太多,无法在e.Result中正常运行。。。但是我只能回来一次,实际上我尝试了变形。为什么太多了?若要异步获取该数据,无论您做什么,都必须在某个变量的非GUI线程上收集该数据,然后调用UI线程并用数据更新UI。BackgroundWorker实际上就是这么做的。如果使用线程,您可以更加灵活,但可能不值得费心。因此,我不确定我是否尝试过BackgroundWorker处理一些真正的大型数据集,但我看不到任何不好的情况会发生,除非它们对于计算机内存来说太大。“TabControl已经进行了延迟加载。”。。找不到