【发布时间】:2019-05-22 17:43:48
【问题描述】:
我看到他们使用 BeginInvoke 从另一个线程更新 UI 的许多代码。是否可以在没有 BeginInvoke 的情况下从异步函数更新 UI?
private async void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
var count = 0;
await Task.Run(() =>
{
for (var i = 0; i <= 500; i++)
{
count = i;
BeginInvoke((Action)(() =>
{
label1.Text = i.ToString();
}));
Thread.Sleep(100);
}
});
label1.Text = @"Counter " + count;
button1.Enabled = true;
}
编辑
请参阅我从链接中获得的以下代码,该链接表明,如果没有 BeginInvoke,我们可以在使用 task.run 时更新 UI。
private readonly SynchronizationContext synchronizationContext;
private DateTime previousTime = DateTime.Now;
public Form1()
{
InitializeComponent();
synchronizationContext = SynchronizationContext.Current;
}
private async void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
var count = 0;
await Task.Run(() =>
{
for (var i = 0; i <= 5000000; i++)
{
UpdateUI(i);
count = i;
}
});
label1.Text = @"Counter " + count;
button1.Enabled = true;
}
public void UpdateUI(int value)
{
var timeNow = DateTime.Now;
if ((DateTime.Now - previousTime).Milliseconds <= 50) return;
synchronizationContext.Post(new SendOrPostCallback(o =>
{
label1.Text = @"Counter " + (int)o;
}), value);
previousTime = timeNow;
}
那么告诉我 synchronizationContext 和 BeginInvoke 两者是一样的吗?应该使用哪一个来从不同的线程更新 UI?哪个效率最高?
请指导我,我是异步/等待和任务用法的新手。
【问题讨论】:
-
创建一个静态webmethod并在时间间隔内用ajax调用它。
-
带 Invoke 的异步代码或不带 Invoke 的同步代码。您不能从另一个线程修改 UI 对象。
-
你为什么要避免
(Begin)Invoke?这些方法是专门为使进程间通信更容易而设计的。我想,你可以看看Task类的ConfigureAwait方法——它处理执行上下文,对你有帮助。 -
@CamiloTerevinto - 异步并不意味着线程化。
-
@HenkHolterman 你说得对,评论不是最好的。 OP is 明确使用多线程