从backgroundworker调用控件停止,没有错误 [英] Invoking a control from backgroundworker stops with no error

查看:150
本文介绍了从backgroundworker调用控件停止,没有错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在运行一个BackgroundWorker,它想更新我的UserControl.我在检查InvokeRequired属性后尝试调用:

I'm running a BackgroundWorker which suppose to update my UserControl. I tried Invoking after checking InvokeRequired property:

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:

I also tried to invoke the RichTextBox inside my UserControl directly:

_ucResultRich.rchResult.Invoke(new Action(() => _ucResultRich.rchResult.Rtf = tmpRich.Rtf));

但是当我调试代码时,它只会停止运行其余代码,而不会出现错误.

But when I debug the code, it just stops running the rest of the code with no error.

_ucResultRich.InvokeRequired_ucResultRich.rchResult.InvokeRequired都返回true.

我在这里做错什么了吗?

Am I doing something wrong here?

更新

我将Invoke部分放在try catch中,现在我可以从异常消息中得到以下错误:

I put the Invoke part in try catch and now I can get the following error from the exception message:

Cross-thread operation not valid: Control '' accessed from a thread 
      other than the thread it was created on.

是因为无法确定控件吗?因为它显示为Control ''.

Is it because it cant determine the control? Cause it shows it like Control ''.

推荐答案

在使用其他线程更新UI线程上的控件时,您需要调用委托而不是Action.

You need to invoke a delegate not an Action when using other threads to update controls on the UI thread.

您可以使用我的通用方法来实现:

You can use my general purpose method to achieve this:

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);
 }
}

您可以这样使用此方法:

And you can use this method like this:

SetControlProperty(_ucResultRich.rchResult, "Rtf", tmpRich.Rtf); 

更新

您可以使用此方法在控件上调用无参数方法:

You can use this method to call parameterless methods on the control:

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());

要调用更复杂的方法,必须为需要调用的方法创建一个适当的委托.

To call more complex methods you must create an appropriate delegate for the method you need to call.

更新2

要从其他线程的属性中获取值,可以使用以下方法:

To get values from properties from other threads you can use this method:

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调用控件停止,没有错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆