盲目铸造与反射线程安全事件调用

时间:2013-07-03 12:52:50

标签: c# thread-safety inversion-of-control invoke

我正在编写一个使用线程的类库,我想把线程安全放到库中,而不是让我们代码的开发人员必须自己实现线程安全。

我有一个活动

public delegate void OnPostHandler();
public event OnPostHandler OnPost;

和方法

public void FireEvent() {
    Delegate[] delegate_list = OnPost.GetInvocationList();
    foreach (OnPostHandler d in delegate_list)
    {
       //detect if d.Target is a System.Windows.Forms.Control
       Type formType = Type.GetType("System.Windows.Forms.Control, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
       if(formType != null) {
           //need to cast d.Target to System.Windows.Forms.Control WITHOUT referencing System.Windows.Forms.Control
           if(d.Target.InvokeRequired) {
               d.Target.Invoke(d);
           } else {
               d();
           }
       } else {
           d();
       }
    }
}

FireEvent内,我想将d.Target投射到System.Windows.Forms.Control,而System.Windows.Forms.Control没有formType作为代码中的指定演员,我希望{{1}}完成{{1}} 1}}如果可能的话,我不会被迫自己链接到表单程序集,因为它不是库的要求而不应该是。

或者,是否有更好的方法来做我想做的事情?

2 个答案:

答案 0 :(得分:1)

通过反思你可以:

Delegate[] delegate_list = OnPost.GetInvocationList();

Type formType = Type.GetType("System.Windows.Forms.Control, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
var invokeRequiredProp = formType.GetProperty("InvokeRequired");

foreach (OnPostHandler d in delegate_list)
{
    if(formType != null) {
        var invokeRequired = invokeRequiredProp.GetValue(d.Target, null);
        if (invokeRequired) {
            formType.GetMethod("Invoke").Invoke(d.Target, new object[]{d});
        } 
        else {
           d();
       }
    } else {
        d();
    }
}

GetMethodGetProperty方法可能需要BindingFlags个参数。

如果没有反映,您可以使用ISynchronizeInvoke

Delegate[] delegate_list = OnPost.GetInvocationList();

foreach (OnPostHandler d in delegate_list)
{
    var form = d.Target as ISynchronizeInvoke;
    if(form != null && form.InvokeRequired) {
      form.Invoke(d);
    } 
    else {
       d();
    }
}

答案 1 :(得分:0)

使用界面ISynchronizeInvoke。它在System中,由System.Windows.Forms.Control实现。