我的任务可能需要一段时间才能完成。
我尝试了一个简单的演示,但由于某些原因它锁定了GUI线程。我认为任务是异步的,GUI会在任务运行时更新。
这可以通过任务吗?
private void button5_Click(object sender, EventArgs e)
{
var task = Task.Factory.StartNew(() => DoSomething());
while (!task.IsCompleted)
{
label1.Text += ".";
if (label1.Text.Length == 5)
label1.Text = ".";
}
}
private void DoSomething()
{
Thread.Sleep(5000);
}
更新:在Damien的回答之后我尝试了以下但是CPU增加了
private void button5_Click(object sender, EventArgs e)
{
var task = Task.Factory.StartNew(() => DoSomething());
}
public delegate void dgUpdateLabel();
private void UpdateLabel()
{
if (this.InvokeRequired)
{
this.BeginInvoke(new dgUpdateLabel(UpdateLabel), new object[] { });
}
else
{
label1.Text += ".";
if (label1.Text.Length == 5)
label1.Text = ".";
}
}
private void DoSomething()
{
var task = Task.Factory.StartNew(() => Sleep());
while (!task.IsCompleted)
{
UpdateLabel();
}
}
private void Sleep()
{
Thread.Sleep(5000);
}
UPDATE2:我认为尝试更新标签的速度太快,无法处理。如果在UpdateLabel方法调用之后放置一个Thread.Sleep(500),它将按预期工作。
答案 0 :(得分:1)
您需要在UI更新之前从button_Click
处理程序返回。也许看看运行计时器,以执行定期更新。
目前,您的UI线程正在紧挨着while (!task.IsCompleted)
运行,可能会耗尽所有CPU。
要使用计时器,您必须在更高级别(例如私有字段)而不是本地变量中公开task
变量。
答案 1 :(得分:0)
根据我们的聊天更新:):
private void Form1_Load(object sender, EventArgs e)
{
CancellationTokenSource cts = new CancellationTokenSource();
Task worker = new Task(() => DoSomething());
Task ui_updater = new Task(() => UpdateGui(CancellationToken token));
worker.Start();
updater.Start();
// Worker task completed, cancel GUI updater.
worker.ContinueWith(task => cts.Cancel());
}
private void DoSomething()
{
// Do an awful lot of work here.
}
private void UpdateGui(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
UpdateLabel();
Thread.Sleep(500);
}
}
private void UpdateLabel()
{
if (this.InvokeRequired)
{
this.BeginInvoke(new Action(() => UpdateLabel()), new object[] { });
}
else
{
label1.Text += ".";
if (label1.Text.Length >= 5)
label1.Text = ".";
}
}
答案 2 :(得分:0)
我调整了Alex's code,IMO有多个错误(并且无法运行):
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WinForm
{
public partial class Form1 : Form
{
readonly CancellationTokenSource _cts = new CancellationTokenSource();
public Form1()
{
InitializeComponent();
}
private void button5_Click(object sender, EventArgs e)
{
var task = Task.Factory.StartNew(() => DoSomething());
Task updatingLabel = Task.Factory.StartNew(() => UpdateLabelValidated(_cts));
task.ContinueWith(_=> _cts.Cancel());
}
private void DoSomething()
{
Thread.Sleep(20000);
}
private void UpdateLabelValidated(CancellationTokenSource token)
{
while (!token.IsCancellationRequested)
{
UpdateLabel();
Thread.Sleep(500);
}
}
private void UpdateLabel()
{
if (this.InvokeRequired)
{
this.BeginInvoke(new Action(UpdateLabel), new object[] { });
}
else
{
label1.Text += ".";
if (label1.Text.Length > 5)
label1.Text = ".";
}
}
}
}