使用asyc await从事件更新UI
我试图了解如何在使用async / await模式时从事件更新UI。 下面是我在WinForm应用程序上使用的测试代码。 我甚至不确定这是正确的方法。 允许pwe_StatusUpdate方法更新UI有什么必要? 抛出跨线程操作错误。
谢谢阅读。
// calling code ProcessWithEvents pwe = new ProcessWithEvents(); pwe.StatusUpdate += pwe_StatusUpdate; await pwe.Run(); void pwe_StatusUpdate(string updateMsg) { // Error Here: Cross-thread operation not valid: Control '_listBox_Output' accessed from a thread other than the thread it was created on. _listBox_Output.Items.Add(updateMsg); }
–
// Class with long running process and event public delegate void StatusUpdateHandler(string updateMsg); public class ProcessWithEvents { public event StatusUpdateHandler StatusUpdate; public async Task Run() { await Task.Run(() => { for (int i = 0; i < 10; i++) { RaiseUpdateEvent(String.Format("Update {0}", i)); Thread.Sleep(500); } }); } private void RaiseUpdateEvent(string msg) { if (StatusUpdate != null) StatusUpdate(msg); } }
–
async
模式支持进度更新 。
简而言之,您的async
方法可以采用IProgress
,并且您的调用代码会传递该接口的实现(通常是Progress
)。
public class ProcessWithUpdates { public async Task Run(IProgress progress) { await Task.Run(() => { for (int i = 0; i < 10; i++) { if (progress != null) progress.Report(String.Format("Update {0}", i)); Thread.Sleep(500); } }); } } // calling code ProcessWithUpdates pwp = new ProcessWithUpdates(); await pwp.Run(new Progress (pwp_StatusUpdate));
您应该使用Control
Invoke
方法。 它在Control的线程中执行一些代码。 您还可以检查InvokeRequired
属性以检查是否需要调用Invoke
方法(它检查调用方是否在与创建控件的线程不同的线程上)。
简单的例子:
void SomeAsyncMethod() { // Do some work if (this.InvokeRequired) { this.Invoke((MethodInvoker)(() => { DoUpdateUI(); } )); } else { DoUpdateUI(); } } void DoUpdateUI() { // Your UI update code here }
在某些情况下,您应该在调用Invoke
方法之前检查Control
的IsHandleCreated
属性。 如果IsHandleCreated
返回false,那么您需要等待Control的句柄创建
//只需像这样声明一个委托
delegate void Add(string msg);
//然后像这样声明委托方法:
var add = new Add((msg) => { _listBox_Output.Items.Add(msg); });
//现在只需调用委托:
void pwe_StatusUpdate(string updateMsg) { _listBox_Output.Invoke(add,updateMsg); }
这是另一个例子
上述就是C#学习教程:使用asyc await从事件更新UI分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
async void DoExport() { var rMsg = ""; var t = await Task.Factory.StartNew(() => ExportAsMonthReport(LastMonth.Name, LastYear.Name, out rMsg)); if (t) { BeginInvoke((Action)(() => { spinnerMain.Visible = false; menuItemMonth.Enabled = true; MetroMessageBox.Show(this, rMsg, "Export", MessageBoxButtons.OK, MessageBoxIcon.Information, 200); })); } else { BeginInvoke((Action)(() => { spinnerMain.Visible = false; menuItemMonth.Enabled = true; MetroMessageBox.Show(this, rMsg, "Export", MessageBoxButtons.OK, MessageBoxIcon.Error, 200); })); } }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1013447.html