I use C# Winforms
I am using Task.Run() in order to get my WinForm does not freeze.
Inside this code, I need to update the textbox text.
I tried to update textbox text directly and through Invoke but non worked.
I tried to minimize my code to just focus on the problem
Any idea how to update the text box inside 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);
}
}));
});
}
CodePudding user response:
You're using Task.Run to run it in a different thread, but then you're using BeginInvoke, which tells it to run that code on the UI thread. So the result is that your code is run on the UI thread. And since you're using Thread.Sleep(), you lock your UI thread.
Instead, run it all on your UI thread and use Task.Delay() instead of Thread.Sleep() to avoid locking the UI thread.
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);
}
}
CodePudding user response:
as pointed out by Gabriel you are running a new thread, and then go back to UI thread right after that witch BeginInvoke. You could go with Gabriel's answer, and run everything on the UI thread, or you could change your code to below, this way you will send information to your UI thread as BeginInvoke suppose to do.
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);
}
});
}
