当我尝试从另一个线程更新 UI 时,应用程序没有响应
Application is not responding, when i tried to updated UI from another thread
执行流程:
- 我从主线程调用了新线程(并行线程),它正在执行一个长时间运行的进程。
- 并行线程正在更新主线程UI。
- 我让我的主线程等待并行线程完成。
- 我需要两个线程之间的同步。
- 我需要在主线程中使用并行线程的结果,所以我阻塞了主线程直到并行处理完成。
这是我的代码有问题,
请提出解决问题的建议。
private readonly AutoResetEvent _resetEvent = new AutoResetEvent(false);
private event EventHandler Workcompleted;
private void button1_Click(object sender, EventArgs e)
{
Workcompleted += Completed;
Thread thr = new Thread(UpdateUI);
thr.Start("");
_resetEvent.WaitOne();
// Logical operation dependent on parallel process final result
}
private void Completed(object sender, EventArgs args)
{
_resetEvent.Set();
}
private void UpdateUI(object txt)
{
for (int i = 0; i < 10; i++)
{
if (label1.InvokeRequired)
{
label1.Invoke(new ParameterizedThreadStart(UpdateUI), i.ToString());
}
else
{
label1.Text = (string)txt;
Thread.Sleep(100);
}
}
if (Workcompleted != null)
Workcompleted(this, new EventArgs());
}
I made my main thread to wait until parallel thread is complete.
你在那里屏蔽了自己。你为什么首先开始一个新线程?保持 UI 响应。现在你还是阻止了它。 不要阻止它。我不知道你想在线程运行时做什么,可能是改变控制状态并在线程完成时重置它们,但是什么您不想 阻塞了您的UI 线程。停下来,找到另一种方法来实现你想要实现的目标。
public delegate void Action();
private void UpdateUI(object txt)
{
this.BeginInvoke((Action)(() =>
{
label2.Text = (string)txt;
}));
}
通过使用这段代码,我们不需要等待另一个线程...
您似乎正在寻找一种方法来报告并行操作过程中 UI 中的进度,并等待最终结果(同步)对其进行处理。
这可以使用 Async/Await
轻松完成,无需 运行 手动线程、同步构造或线程编组(对于 UI 调用),最重要的是不会阻塞 UI线程。
这是一个示例,说明如何 运行 并行操作、向 UI 报告进度、持续更新 UI 并最终在结果可用时对其进行处理.
private async void button1_Click(object sender, EventArgs e)
{
var progress = new Progress<int>(ShowProgressInUi);
var result = await Task.Run(() => DoParallelWorkAsync(progress));
// Do something with final result
label1.Text = result;
}
private void ShowProgressInUi(int progress)
{
label1.Text = string.Format("Progress: {0} % done...", progress);
}
private static async Task<string> DoParallelWorkAsync(IProgress<int> progress)
{
// This work is done in a separate thread.
// In this case a background thread (from the thread pool),
// but could be run on a foreground thread if the work is lengthy.
for (var i = 1; i <= 10; i++)
{
// Simulate workload
await Task.Delay(100);
progress.Report(i * 10);
}
return "All done";
}
执行流程:
- 我从主线程调用了新线程(并行线程),它正在执行一个长时间运行的进程。
- 并行线程正在更新主线程UI。
- 我让我的主线程等待并行线程完成。
- 我需要两个线程之间的同步。
- 我需要在主线程中使用并行线程的结果,所以我阻塞了主线程直到并行处理完成。
这是我的代码有问题, 请提出解决问题的建议。
private readonly AutoResetEvent _resetEvent = new AutoResetEvent(false);
private event EventHandler Workcompleted;
private void button1_Click(object sender, EventArgs e)
{
Workcompleted += Completed;
Thread thr = new Thread(UpdateUI);
thr.Start("");
_resetEvent.WaitOne();
// Logical operation dependent on parallel process final result
}
private void Completed(object sender, EventArgs args)
{
_resetEvent.Set();
}
private void UpdateUI(object txt)
{
for (int i = 0; i < 10; i++)
{
if (label1.InvokeRequired)
{
label1.Invoke(new ParameterizedThreadStart(UpdateUI), i.ToString());
}
else
{
label1.Text = (string)txt;
Thread.Sleep(100);
}
}
if (Workcompleted != null)
Workcompleted(this, new EventArgs());
}
I made my main thread to wait until parallel thread is complete.
你在那里屏蔽了自己。你为什么首先开始一个新线程?保持 UI 响应。现在你还是阻止了它。 不要阻止它。我不知道你想在线程运行时做什么,可能是改变控制状态并在线程完成时重置它们,但是什么您不想 阻塞了您的UI 线程。停下来,找到另一种方法来实现你想要实现的目标。
public delegate void Action();
private void UpdateUI(object txt)
{
this.BeginInvoke((Action)(() =>
{
label2.Text = (string)txt;
}));
}
通过使用这段代码,我们不需要等待另一个线程...
您似乎正在寻找一种方法来报告并行操作过程中 UI 中的进度,并等待最终结果(同步)对其进行处理。
这可以使用 Async/Await
轻松完成,无需 运行 手动线程、同步构造或线程编组(对于 UI 调用),最重要的是不会阻塞 UI线程。
这是一个示例,说明如何 运行 并行操作、向 UI 报告进度、持续更新 UI 并最终在结果可用时对其进行处理.
private async void button1_Click(object sender, EventArgs e)
{
var progress = new Progress<int>(ShowProgressInUi);
var result = await Task.Run(() => DoParallelWorkAsync(progress));
// Do something with final result
label1.Text = result;
}
private void ShowProgressInUi(int progress)
{
label1.Text = string.Format("Progress: {0} % done...", progress);
}
private static async Task<string> DoParallelWorkAsync(IProgress<int> progress)
{
// This work is done in a separate thread.
// In this case a background thread (from the thread pool),
// but could be run on a foreground thread if the work is lengthy.
for (var i = 1; i <= 10; i++)
{
// Simulate workload
await Task.Delay(100);
progress.Report(i * 10);
}
return "All done";
}