与UI对话的线程
本文关键字:线程 对话 UI | 更新日期: 2023-09-27 18:09:52
我有这样的代码:
private void buttonStart_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() => GeneraListaCartelle())
.ContinueWith(t => GeneraListaCartelleCompletata()
, CancellationToken.None
, TaskContinuationOptions.None
, TaskScheduler.FromCurrentSynchronizationContext());
}
private void GeneraListaCartelle()
{
try
{
... some operation ....
}
catch (Exception err)
{
txtErrors.AppendText(err.Message);
}
}
GeneraListaCartelleCompletata()
{
... process finished...
}
和txtErrors
在"主"线程(UI)中。当我捕获一个错误时,异步线程不能写入UI控件,我得到一个invalid cross-thread exception
。
我可以在线程内与UI对话吗?
如果你使用的是WinForms,你需要在ui线程上调用你的方法,就像
catch (Exception err)
{
if(this.InvokeRequired){
Action<Exception> act = ((ex) => {
txtErrors.AppendText(ex.Message);
});
this.Invoke(act, new object[] { err });
}
else{
txtErrors.AppendText(err.Message);
}
}
如果您使用的是WPF,则需要
catch (Exception err)
{
if(this.Dispatcher.CheckAccess()){
txtErrors.AppendText(err.Message);
}
else {
Action<Exception> act = ((ex) => {
txtErrors.AppendText(ex.Message);
});
this.Dispatcher.Invoke(act, new object[] { err });
}
}
如果您的目标是WinForm应用程序,那么:
try
{
... some operation ....
}
catch (Exception err)
{
if (txtErrors.InvokeRequired)
{
txtErrors.BeginInvoke(new MethodInvoker(
delegate { txtErrors.AppendText(err.Message); })
);
}
}
有一个来自msdn:
的例子// This delegate enables asynchronous calls for setting
// the text property on a TextBox control.
delegate void SetTextCallback(string text);
// This method demonstrates a pattern for making thread-safe
// calls on a Windows Forms control.
//
// If the calling thread is different from the thread that
// created the TextBox control, this method creates a
// SetTextCallback and calls itself asynchronously using the
// Invoke method.
//
// If the calling thread is the same as the thread that created
// the TextBox control, the Text property is set directly.
private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.textBox1.Text = text;
}
}
在调用的form_load事件处理程序中设置CheckForIllegalCrossThreadCalls为false
从一个旧项目中取出,我不得不处理从另一个线程更新UI。应该对你也有用。
delegate void addtoValProg();
addtoValProg myDelegate;
myDelegate = new addtoValProg(invokeControl);
private void GeneraListaCartelle()
{
try
{
//... some operation ....
}
catch (Exception err)
{
invokeControl();
}
}
private void invokeControl()
{
if (this.InvokeRequired)
{
this.Invoke(this.myDelegate);
}
else
{
txtErrors.AppendText(err.Message);
txtErrors.Update();
}
}