dev*_*ife 12 winforms task-parallel-library
我有一个简单的小winforms应用程序,通过TPL任务在另一个线程上执行长时间运行的进程.在这个漫长的运行过程中,我想更新UI(进度条或其他内容).有没有办法这样做而不需要.ContinueWith()?
public partial class Form1 : Form
{
private Task _childTask;
public Form1()
{
InitializeComponent();
Task.Factory.StartNew(() =>
{
// Do some work
Thread.Sleep(1000);
// Update the UI
_childTask.Start();
// Do more work
Thread.Sleep(1000);
});
_childTask = new Task((antecedent) =>
{
Thread.Sleep(2000);
textBox1.Text = "From child task";
}, TaskScheduler.FromCurrentSynchronizationContext());
}
}
Run Code Online (Sandbox Code Playgroud)
执行此代码我得到无处不在的异常:
跨线程操作无效:控制'textBox1'从其创建的线程以外的线程访问.
Dre*_*rsh 16
是的,您可以显式调用BeginInvoke要与之通信的Window/Control.在你的情况下,这将是这样的:
this.textBox.BeginInvoke(new Action(() =>
{
this.textBox.Text = "From child task.";
}));
Run Code Online (Sandbox Code Playgroud)
你正在传递TaskScheduleras state(或者antecedent,就像你所说的那样).这没有多大意义.
我不确定你到底想做什么,但是你需要指定TaskScheduler你何时开始Task,而不是在你创建时.此外,它似乎childTask不一定是一个领域:
var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task childTask = null;
Task.Factory.StartNew(
() =>
{
Thread.Sleep(1000);
childTask.Start(scheduler);
Thread.Sleep(1000);
});
childTask = new Task(
() =>
{
Thread.Sleep(2000);
textBox1.Text = "From child task";
});
Run Code Online (Sandbox Code Playgroud)
当然,使用C#5和所有这些都会更容易await:
public Form1()
{
InitializeComponent();
StartAsync();
}
private async void StartAsync()
{
// do some work
await Task.Run(() => { Thread.Sleep(1000); });
// start more work
var moreWork = Task.Run(() => { Thread.Sleep(1000); });
// update the UI, based on data from “some work”
textBox1.Text = "From async method";
// wait until “more work” finishes
await moreWork;
}
Run Code Online (Sandbox Code Playgroud)
你不能创建async构造函数,但是你可以从中运行一个async方法."正在工作"不会在UI线程上运行,因为它是通过显式启动的Task.Run().但由于StartAsync()直接调用,它在UI线程上执行.
| 归档时间: |
|
| 查看次数: |
9253 次 |
| 最近记录: |