有没有办法同时调用多个方法?我有一个winforms应用程序,在加载时加载了大量的数据:
private void form1_Load(object sender, EventArgs e)
{
LoadValues1();
LoadValues2();
LoadValues3();
LoadValues4();
LoadValues5();
LoadValues6();
LoadValues7();
LoadValues8();
}
这些方法检索数据并填充DevExpress LookUpEdits(类似于windows下拉列表),所以它们看起来像这样:
DBContext dbContext = new DBContext();
ObservableCollection<string> values1 =
new ObservableCollection<string>((from i in dbContext.Items
where i.Value1 != null
&& i.Value1.Length > 0
orderby i.Value1
select i.Value1).Distinct());
lookupValues1.Properties.DataSource = descModelYear;
DevExpress.XtraEditors.Controls.LookUpColumnInfoCollection colInfo = lookupValues1.Properties.Columns;
colInfo.Clear();
colInfo.Add(new DevExpress.XtraEditors.Controls.LookUpColumnInfo("Column"));
colInfo[0].Caption = "Values 1";
这些方法中的一些需要一段时间才能完成,但它们都没有相互依赖,所以我想我可以同时完成所有这些:
Task.Factory.StartNew(() => LoadValues1());
Task.Factory.StartNew(() => LoadValues2());
etc.
但是当第二个任务运行时我一直收到错误,说无法从与创建它不同的线程访问控件。
感谢任何帮助!
答案 0 :(得分:2)
正如其他人指出的那样,您需要确保在访问UI元素时,您需要确保在正确阅读时执行此操作。这很容易使用任务并行库,如下所示:
private TaskScheduler m_TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
拥有TaskScheduler后,您可以将任务安排在UI线程上运行,如下所示:
Task.Factory.StartNew(() =>
{
LoadValues1();
}, CancellationToken.None, TaskCreationOptions.None, m_TaskScheduler);
这里需要注意的是,在UI线程上运行所有任务可能仍会锁定您。我建议您创建一些类或一组集合,您可以填充相关信息,然后一旦所有数据都在那里,您可以在UI线程上调用另一个方法,将控件绑定到数据或执行您需要的任何UI特定操作。
答案 1 :(得分:1)
在操作UI控件时,必须在创建控件的同一线程上执行此操作。在这种情况下,您应该只运行那些同步修改UI的方法。如果所有方法都修改了UI,则应该拆分工作,以便仅在UI线程上调用修改UI的代码。
通常,您可以使用InvokeRequired
检查您是否在正确的线程上,并Invoke
在UI线程上运行方法。
答案 2 :(得分:0)
您应该以不同的单位分离逻辑,并尝试将UI逻辑放在一个位置。
//private fields
private readonly DBContext _dbContext = new DBContext();
private Task<ICollection<string>> GetValues1()
{
return Task.Run(() =>
{
return (from i in _dbContext.Items
where i.Value1 != null
&& i.Value1.Length > 0
orderby i.Value1
select i.Value1)
.Distinct()
.ToList();
};
}
private void LoadUIElements1(ICollection<string> values)
{
var observableValues = new ObservableCollection<string>(values);
lookupValues1.Properties.DataSource = descModelYear;
DevExpress.XtraEditors.Controls.LookUpColumnInfoCollection colInfo = lookupValues1.Properties.Columns;
colInfo.Clear();
colInfo.Add(new DevExpress.XtraEditors.Controls.LookUpColumnInfo("Column"));
colInfo[0].Caption = "Values 1";
}
private async void form1_Load(object sender, EventArgs e)
{
var tasks = new List<Task>();
// Start each UI task so they will complete independently.
var uiTask1 = GetValues1()
.ContinueWith(t =>
LoadUIElements1(t.Result),
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext());
tasks.Add(uiTask1);
// Wait for all the tasks to complete
Task.WaitAll(tasks.ToArray());
tasks.Clear();
}