我的文本框在 Task.Run 内时没有改变
My Textbox does not change when inside Task.Run
我使用 C# Winforms
我正在使用 Task.Run()
以使我的 WinForm 不冻结。
在此代码中,我需要更新文本框文本。
我尝试直接和通过调用更新文本框文本,但没有成功。
我尽量减少我的代码以专注于问题
知道如何更新 Task.Run()
中的文本框吗?
public async void MyFunction()
{
await Task.Run(() =>
{
lvwFiles.BeginInvoke(new Action(() =>
{
foreach (ListViewItem item in this.lvwFiles.Items)
{
txtLog.Text = item.Text + "\r\n" +txtLog.Text;
if (txtLog.InvokeRequired)
{
txtLog.Invoke(new MethodInvoker(delegate { txtLog.Text = item.Text + "\r\n" + txtLog.Text; }));
}
Thread.Sleep(4000);
item.BackColor = Color.FromArgb(128, 255, 128);
}
}));
});
}
您在不同的线程中使用 Task.Run
到 运行,但随后您使用 BeginInvoke
,它告诉它 运行 该代码UI 线程。所以结果就是你的代码在UI线程上运行。由于您正在使用 Thread.Sleep()
,因此您锁定了 UI 线程。
相反,运行 这一切都在您的 UI 线程上,并使用 Task.Delay()
而不是 Thread.Sleep()
以避免锁定 UI 线程。
public async void MyFunction()
{
foreach (ListViewItem item in this.lvwFiles.Items)
{
txtLog.Text = item.Text + "\r\n" + txtLog.Text;
await Task.Delay(4000);
item.BackColor = Color.FromArgb(128, 255, 128);
}
}
正如 Gabriel 所指出的那样,您正在 运行 创建一个新线程,然后在 BeginInvoke
之后立即返回 UI 线程。您可以使用 Gabriel 的回答,运行 UI 线程中的所有内容,或者您可以将代码更改为以下内容,这样您就可以将信息作为 [=11] 发送到 UI 线程=] 假设做。
public async void MyFunction()
{
//run your code on new thread
await Task.Run(() =>
{
foreach (ListViewItem item in this.lvwFiles.Items)
{
//whatever has to trigger that UI update is required
if (txtLog.InvokeRequired)
{
//update UI thread
Dispatcher.BeginInvoke(new Action(() => txtLog.Text = item.Text + "\r\n" + txtLog.Text));
}
// Thread.Sleep(4000); -> I'm not sure if sleep or delay would be required, for me, it looks like a waste of time. And 4 seconds is quite a lot.
//this also looks like UI update, if so, add to dispatcher, or create another one when needed.
item.BackColor = Color.FromArgb(128, 255, 128);
}
});
}
我使用 C# Winforms
我正在使用 Task.Run()
以使我的 WinForm 不冻结。
在此代码中,我需要更新文本框文本。
我尝试直接和通过调用更新文本框文本,但没有成功。
我尽量减少我的代码以专注于问题
知道如何更新 Task.Run()
中的文本框吗?
public async void MyFunction()
{
await Task.Run(() =>
{
lvwFiles.BeginInvoke(new Action(() =>
{
foreach (ListViewItem item in this.lvwFiles.Items)
{
txtLog.Text = item.Text + "\r\n" +txtLog.Text;
if (txtLog.InvokeRequired)
{
txtLog.Invoke(new MethodInvoker(delegate { txtLog.Text = item.Text + "\r\n" + txtLog.Text; }));
}
Thread.Sleep(4000);
item.BackColor = Color.FromArgb(128, 255, 128);
}
}));
});
}
您在不同的线程中使用 Task.Run
到 运行,但随后您使用 BeginInvoke
,它告诉它 运行 该代码UI 线程。所以结果就是你的代码在UI线程上运行。由于您正在使用 Thread.Sleep()
,因此您锁定了 UI 线程。
相反,运行 这一切都在您的 UI 线程上,并使用 Task.Delay()
而不是 Thread.Sleep()
以避免锁定 UI 线程。
public async void MyFunction()
{
foreach (ListViewItem item in this.lvwFiles.Items)
{
txtLog.Text = item.Text + "\r\n" + txtLog.Text;
await Task.Delay(4000);
item.BackColor = Color.FromArgb(128, 255, 128);
}
}
正如 Gabriel 所指出的那样,您正在 运行 创建一个新线程,然后在 BeginInvoke
之后立即返回 UI 线程。您可以使用 Gabriel 的回答,运行 UI 线程中的所有内容,或者您可以将代码更改为以下内容,这样您就可以将信息作为 [=11] 发送到 UI 线程=] 假设做。
public async void MyFunction()
{
//run your code on new thread
await Task.Run(() =>
{
foreach (ListViewItem item in this.lvwFiles.Items)
{
//whatever has to trigger that UI update is required
if (txtLog.InvokeRequired)
{
//update UI thread
Dispatcher.BeginInvoke(new Action(() => txtLog.Text = item.Text + "\r\n" + txtLog.Text));
}
// Thread.Sleep(4000); -> I'm not sure if sleep or delay would be required, for me, it looks like a waste of time. And 4 seconds is quite a lot.
//this also looks like UI update, if so, add to dispatcher, or create another one when needed.
item.BackColor = Color.FromArgb(128, 255, 128);
}
});
}