异步任务中的 C# 更改标签文本
C# in Async Task change Label Text
以下代码不更改文本并停止执行任务
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "Test";
Task.Run(() => MyAsyncMethod());
}
public async Task MyAsyncMethod()
{
label1.Text = "";
//everything from here on will not be executed
}
如果您可以将异步与 UI
一起使用,那将非常方便
通过您需要调用的第二个线程访问 GUI 控件。
以下示例显示如何正确设置标签的文本
private void setLabel1TextSafe(string txt)
{
if(label1.InvokeRequired)
label1.Invoke(new Action(() => label1.Text = txt));
else
label1.Text = txt;
}
希望这能解决您的问题
Task.Run
用于将 Action(非异步)封装到 Task 中。应等待您要执行的任何任务。因此,你的Task.Run
严格来说是无所事事。
将您的 button1_Click
事件处理程序标记为异步。然后删除 Task.Run
而不是等待 MyAsyncMethod()
.
试试这个。您不需要触发新线程来调用异步方法。编译器会为你做。
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "Test";
MyAsyncMethod();
}
public async Task MyAsyncMethod()
{
return await Task.Run(() =>{
label1.Text = "";
//everything from here on will not be executed
}
}
would be really handy if you could use async together with the UI
async
的设计经过精心设计,因此您可以 自然地将其与 UI 一起使用。
in my code i run a function that does a lot of IO and stuff that takes a long time
如果你有异步 I/O 方法(你应该有),那么你可以这样做:
private async void button1_Click(object sender, EventArgs e)
{
label1.Text = "Test";
await MyMethodAsync();
}
public async Task MyMethodAsync()
{
label1.Text = "";
await ...; // "lot of IO and stuff"
label1.Text = "Done";
}
这是最自然的方法。
但是,如果您需要到运行后台线程上的代码(例如,它实际上是CPU绑定的,或者如果您只是不不想让你的 I/O 操作像他们应该的那样异步),那么你可以使用 IProgress<T>
:
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "Test";
var progress = new Progress<string>(update => { label1.Text = update; });
await Task.Run(() => MyMethod(progress));
}
public void MyMethod(IProgress<string> progress)
{
if (progress != null)
progress.Report("");
...; // "lot of IO and stuff"
if (progress != null)
progress.Report("Done");
}
现代代码在任何情况下都不应使用 Control.Invoke
或(甚至更糟)Control.InvokeRequired
.
我认为问题和部分答案都不清楚。根据任务线程中您需要更新必须使用调用的标签的位置。否则,您可以利用 await 并利用标准语义。
private async void button1_Click(object sender, EventArgs e)
{
label1.Text = "Starting to run a long task... carry on...";
await snooze(3);
label1.Text = "Done with long task";
}
public Task<int> snooze(int seconds)
{
label1.Text = "zzzz...";
return Task.Run(
() => {
label1.Invoke(new Action(() => label1.Text = "For some reason I need to alert you here.. bad dream perhaps...direct access to label1 will fail"));
Thread.Sleep(seconds * 1000);
return seconds;
});
}
以下代码不更改文本并停止执行任务
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "Test";
Task.Run(() => MyAsyncMethod());
}
public async Task MyAsyncMethod()
{
label1.Text = "";
//everything from here on will not be executed
}
如果您可以将异步与 UI
一起使用,那将非常方便通过您需要调用的第二个线程访问 GUI 控件。 以下示例显示如何正确设置标签的文本
private void setLabel1TextSafe(string txt)
{
if(label1.InvokeRequired)
label1.Invoke(new Action(() => label1.Text = txt));
else
label1.Text = txt;
}
希望这能解决您的问题
Task.Run
用于将 Action(非异步)封装到 Task 中。应等待您要执行的任何任务。因此,你的Task.Run
严格来说是无所事事。
将您的 button1_Click
事件处理程序标记为异步。然后删除 Task.Run
而不是等待 MyAsyncMethod()
.
试试这个。您不需要触发新线程来调用异步方法。编译器会为你做。
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "Test";
MyAsyncMethod();
}
public async Task MyAsyncMethod()
{
return await Task.Run(() =>{
label1.Text = "";
//everything from here on will not be executed
}
}
would be really handy if you could use async together with the UI
async
的设计经过精心设计,因此您可以 自然地将其与 UI 一起使用。
in my code i run a function that does a lot of IO and stuff that takes a long time
如果你有异步 I/O 方法(你应该有),那么你可以这样做:
private async void button1_Click(object sender, EventArgs e)
{
label1.Text = "Test";
await MyMethodAsync();
}
public async Task MyMethodAsync()
{
label1.Text = "";
await ...; // "lot of IO and stuff"
label1.Text = "Done";
}
这是最自然的方法。
但是,如果您需要到运行后台线程上的代码(例如,它实际上是CPU绑定的,或者如果您只是不不想让你的 I/O 操作像他们应该的那样异步),那么你可以使用 IProgress<T>
:
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "Test";
var progress = new Progress<string>(update => { label1.Text = update; });
await Task.Run(() => MyMethod(progress));
}
public void MyMethod(IProgress<string> progress)
{
if (progress != null)
progress.Report("");
...; // "lot of IO and stuff"
if (progress != null)
progress.Report("Done");
}
现代代码在任何情况下都不应使用 Control.Invoke
或(甚至更糟)Control.InvokeRequired
.
我认为问题和部分答案都不清楚。根据任务线程中您需要更新必须使用调用的标签的位置。否则,您可以利用 await 并利用标准语义。
private async void button1_Click(object sender, EventArgs e)
{
label1.Text = "Starting to run a long task... carry on...";
await snooze(3);
label1.Text = "Done with long task";
}
public Task<int> snooze(int seconds)
{
label1.Text = "zzzz...";
return Task.Run(
() => {
label1.Invoke(new Action(() => label1.Text = "For some reason I need to alert you here.. bad dream perhaps...direct access to label1 will fail"));
Thread.Sleep(seconds * 1000);
return seconds;
});
}