从 backgroundworker 调用控件停止没有错误
Invoking a control from backgroundworker stops with no error
我是 运行 一个 BackgroundWorker
,我想更新我的 UserControl
。我在检查 InvokeRequired
属性:
后尝试调用
private void bgwHighlightText_DoWork(object sender, DoWorkEventArgs e)
{
tmpRich.SelectedRtf = myRtf;
if (_ucResultRich.InvokeRequired && _ucResultRich.rchResult.InvokeRequired)
_ucResultRich.Invoke(new Action(() => _ucResultRich.rchResult.Rtf = tmpRich.Rtf)); // Debug pointer stops here
//Rest of the code
}
我也尝试直接调用 UserControl
中的 RichTextBox
:
_ucResultRich.rchResult.Invoke(new Action(() => _ucResultRich.rchResult.Rtf = tmpRich.Rtf));
但是当我调试代码时,它只是停止 运行 其余代码而没有错误。
_ucResultRich.InvokeRequired
和 _ucResultRich.rchResult.InvokeRequired
return true
。
我是不是做错了什么?
更新
我把 Invoke
部分放在 try catch
中,现在我可以从异常消息中得到以下错误:
Cross-thread operation not valid: Control '' accessed from a thread
other than the thread it was created on.
是不是因为无法判断控件?因为它显示为 Control ''
.
当使用其他线程更新 UI 线程上的控件时,您需要调用委托而不是 Action。
您可以使用我的通用方法来实现:
public delegate void SetControlPropertyDelegateHandler(Control control, string propertyName, object value);
public static void SetControlProperty(Control control, string propertyName, object value)
{
if (control == null)
return;
if (control.InvokeRequired)
{
SetControlPropertyDelegateHandler dlg = new SetControlPropertyDelegateHandler(SetControlProperty);
control.Invoke(dlg, control, propertyName, value);
}
else
{
PropertyInfo property = control.GetType().GetProperty(propertyName);
if (property != null)
property.SetValue(control, value, null);
}
}
你可以像这样使用这个方法:
SetControlProperty(_ucResultRich.rchResult, "Rtf", tmpRich.Rtf);
更新
您可以使用此方法调用控件上的无参数方法:
public static void CallMethodUsingInvoke(Control control, Action methodOnControl)
{
if (control == null)
return;
var dlg = new MethodInvoker(methodOnControl);
control.Invoke(dlg, control, methodOnControl);
}
示例:
CallMethodUsingInvoke(richTextBox1, () => _ucResultRich.rchResult.SelectAll());
要调用更复杂的方法,您必须为需要调用的方法创建适当的委托。
更新 2
要从其他线程的属性中获取值,您可以使用此方法:
public delegate object GetControlPropertyValueDelegate(Control controlToModify, string propertyName);
public static T GetControlPropertyValue<T>(Control controlToModify, string propertyName)
{
if (controlToModify.InvokeRequired)
{
var dlg = new GetControlPropertyValueDelegate(GetControlPropertyValue);
return (T)controlToModify.Invoke(dlg, controlToModify, propertyName);
}
else
{
var prop = controlToModify.GetType().GetProperty(propertyName);
if (prop != null)
{
return (T)Convert.ChangeType(prop.GetValue(controlToModify, null), typeof(T));
}
}
return default (T);
}
示例:
var textLength = GetControlPropertyValue<int>(_ucResultRich.rchResult, "Length");
我是 运行 一个 BackgroundWorker
,我想更新我的 UserControl
。我在检查 InvokeRequired
属性:
private void bgwHighlightText_DoWork(object sender, DoWorkEventArgs e)
{
tmpRich.SelectedRtf = myRtf;
if (_ucResultRich.InvokeRequired && _ucResultRich.rchResult.InvokeRequired)
_ucResultRich.Invoke(new Action(() => _ucResultRich.rchResult.Rtf = tmpRich.Rtf)); // Debug pointer stops here
//Rest of the code
}
我也尝试直接调用 UserControl
中的 RichTextBox
:
_ucResultRich.rchResult.Invoke(new Action(() => _ucResultRich.rchResult.Rtf = tmpRich.Rtf));
但是当我调试代码时,它只是停止 运行 其余代码而没有错误。
_ucResultRich.InvokeRequired
和 _ucResultRich.rchResult.InvokeRequired
return true
。
我是不是做错了什么?
更新
我把 Invoke
部分放在 try catch
中,现在我可以从异常消息中得到以下错误:
Cross-thread operation not valid: Control '' accessed from a thread
other than the thread it was created on.
是不是因为无法判断控件?因为它显示为 Control ''
.
当使用其他线程更新 UI 线程上的控件时,您需要调用委托而不是 Action。
您可以使用我的通用方法来实现:
public delegate void SetControlPropertyDelegateHandler(Control control, string propertyName, object value);
public static void SetControlProperty(Control control, string propertyName, object value)
{
if (control == null)
return;
if (control.InvokeRequired)
{
SetControlPropertyDelegateHandler dlg = new SetControlPropertyDelegateHandler(SetControlProperty);
control.Invoke(dlg, control, propertyName, value);
}
else
{
PropertyInfo property = control.GetType().GetProperty(propertyName);
if (property != null)
property.SetValue(control, value, null);
}
}
你可以像这样使用这个方法:
SetControlProperty(_ucResultRich.rchResult, "Rtf", tmpRich.Rtf);
更新
您可以使用此方法调用控件上的无参数方法:
public static void CallMethodUsingInvoke(Control control, Action methodOnControl)
{
if (control == null)
return;
var dlg = new MethodInvoker(methodOnControl);
control.Invoke(dlg, control, methodOnControl);
}
示例:
CallMethodUsingInvoke(richTextBox1, () => _ucResultRich.rchResult.SelectAll());
要调用更复杂的方法,您必须为需要调用的方法创建适当的委托。
更新 2
要从其他线程的属性中获取值,您可以使用此方法:
public delegate object GetControlPropertyValueDelegate(Control controlToModify, string propertyName);
public static T GetControlPropertyValue<T>(Control controlToModify, string propertyName)
{
if (controlToModify.InvokeRequired)
{
var dlg = new GetControlPropertyValueDelegate(GetControlPropertyValue);
return (T)controlToModify.Invoke(dlg, controlToModify, propertyName);
}
else
{
var prop = controlToModify.GetType().GetProperty(propertyName);
if (prop != null)
{
return (T)Convert.ChangeType(prop.GetValue(controlToModify, null), typeof(T));
}
}
return default (T);
}
示例:
var textLength = GetControlPropertyValue<int>(_ucResultRich.rchResult, "Length");