.net框架下的并行任务
本文关键字:并行任务 框架 net | 更新日期: 2023-09-27 18:02:26
我正在研究并行性,想知道你推荐我访问其他头部元素的方式,例如imagima,我会用一些名字填充一个组合框,查询数据库,我会并行做,但我不能做一个组合框。从任务中添加(结果),你推荐我用哪种方法?
一个简单的例子来理解我的问题:
private void button1_Click (object sender, EventArgs e)
{
Task task = new Task (new Action (Count));
task.Start ();
}
void Count ()
{
for (int i = 0; i <99; i + +)
{
Thread.Sleep (1);
progressBar1.Value = i;
}
}
传递进度条值的时间导致错误
如果要调度访问UI控件的任务,则需要将当前同步上下文传递给调度程序。如果您这样做,调度程序将确保您的任务在正确的线程上执行。例如
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() => {
// code that access UI controls
}, uiScheduler);
更多信息请参见http://msdn.microsoft.com/en-us/library/dd997402.aspx
您不能直接访问另一个线程上的控件。您必须首先调用它们。阅读本文:http://msdn.microsoft.com/en-us/library/ms171728.aspx
这是关于如果你把这篇文章翻译成你自己使用的样子:(未测试)
delegate void SetProgressBarCallback();
private void SetProgressBar()
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.progressBar1.InvokeRequired)
{
SetProgressBarCallback d = new SettProgressBarCallback(SetProgressBar);
this.Invoke(d);
}
else
{
for(int i=0; i<99; i++)
{
Thread.Sleep(1);
progressBar1.Value = i;
}
}
}
只是一个快速提示…WinForms中的UI只能从UI线程更新。也许你应该考虑使用Control.Invoke
来更新你的progressBar1
Ryan的答案是正确的,但是他把sleep放在了调用中,这导致程序挂起。下面是一个示例,使用了他所做的相同的事情,但它没有在调用中放置sleep。
private void button1_Click (object sender, EventArgs e)
{
Task task = new Task (new Action (Count));
task.Start ();
}
void Count ()
{
for (int i = 0; i <99; i + +)
{
Thread.Sleep (1);
if(progressBar1.InvokeRequired)
{
int j = i; //This is required to capture the variable, if you do not do this
// the delegate may not have the correct value when you run it;
progressBar1.Invoke(new Action(() => progressBar1.Value = j));
}
else
{
progressBar1.Value = i;
}
}
}
必须执行int j = i
来捕获变量,否则可能会在循环中显示i的错误值。