表单在异步任务完成时无响应



我有一个窗体,需要一些时间从数据库加载值到一些组合框(3个组合框)。为了使表单启动,我添加了一些异步代码来等待每个组合框的加载。目标是加载表单并分配数据源/在数据通过时重新启用组合框,而不会在分配组合框数据源时阻塞表单。

即使使用异步调用,表单也会被阻塞,直到为组合框加载了所有数据源。

如果您能指点我正确的方向,我将不胜感激。

private void FrmOrderSearch_Load(object sender, EventArgs e)
{
//set everything disabled to let the user know we're working on getting the long running data
cbLanguages.DataSource = null;
cbLanguages.Items.Clear();
cbLanguages.Items.Add("Retrieving...");
cbLanguages.SelectedIndex = 0;
cbLanguages.Enabled = false;
cbInterpreter.DataSource = null;
cbInterpreter.Items.Clear();
cbInterpreter.Items.Add("Retrieving...");
cbInterpreter.SelectedIndex = 0;
cbInterpreter.Enabled = false;
cbCustomer.DataSource = null;
cbCustomer.Items.Clear();
cbCustomer.Items.Add("Retrieving...");
cbCustomer.SelectedIndex = 0;
cbCustomer.Enabled = false;
Cursor = Cursors.Default;
}
//added so that form renders before async stuff starts
private async void FrmOrderSearch_Shown(object sender, EventArgs e)
{
Application.DoEvents(); //finish everything up before doing async loads
await getCustomersAsync();
await getInterpretersAsync();
await getLanguagesAsync();
}
private async Task getLanguagesAsync()
{
cbLanguages.DataSource = await Task.Run(() => MemoryObjects.LanguagesList);
cbLanguages.ValueMember = "Code";
cbLanguages.DisplayMember = "Language";
cbLanguages.SelectedIndex = 0;
cbLanguages.Enabled = true;
}
private async Task getInterpretersAsync()
{
cbInterpreter.DataSource = await Task.Run(() => MemoryObjects.InterpreterNamesFacadeList);
cbInterpreter.ValueMember = "IntNo";
cbInterpreter.DisplayMember = "FullName";
cbInterpreter.Enabled = true;
}
private async Task getCustomersAsync()
{
cbCustomer.DataSource = await Task.Run(() => MemoryObjects.CustomerNamesFacadeList);
cbCustomer.ValueMember = "CustNo";
cbCustomer.DisplayMember = "Name";
cbCustomer.Enabled = true;
}

我认为(视觉上的)问题是表单的Shown事件在它完全完成绘制之前被调用。

在这种情况下,我使用的一个技巧是使用Application.Idle事件来调用这些后台任务,而不是使用Shown事件。

订阅Idle event in formLoad ',如下所示:

private void FrmOrderSearch_Load(object sender, EventArgs e)
{
// ........other code
Application.Idle += Application_Idle;
}
现在Idle事件处理程序:
private void Application_Idle(object sender, EventArgs e)
{
Application.Idle -= Application_Idle; // Should only be called once.
// Add all your background jobs (from the `Shown` event)    
}

现在应用程序在后台任务被调用之前已经完成了绘制。

然而,这并不能解决真正的问题,为什么那些后台工作这么慢。根据目前的情况,我们帮不了你。

最新更新