6

我有一个遗留项目,它有数百个 Winforms 事件的方法签名。显然,目前我不想去做 BeginInvoke/EndInvoke,因为这会导致 UI 跨线程问题。

但是我需要(因为死锁)能够将这些签名标记为异步来处理我们必须能够执行的一些异步命令。除了死锁之外,没有其他方法会导致任何结果。

我可以使用 BeginInvoke 成功调用该事件,它可以正常工作并且异步正常等。但是,这会将它分解到另一个线程并破坏我们不想经历的旧实现并使异步和 Invoke 感知。

因此,我正在调查使用 event.GetInvokationList() 并分别循环和调用每个。如果方法是异步的,则开始/结束调用。否则直接在 UI 线程上调用它。

我唯一的问题是我无法通过反射找到任何方法来判断方法签名是否是异步的。

任何人都知道如何从 MethodInfo 或 GetInvokationList() 值中判断一个方法是否是异步的?

谢谢!

4

3 回答 3

3

如果您使用的是 .net 4.5,请尝试“AsyncStateMachineAttribute”。 http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.asyncstatemachineattribute.aspx

于 2013-09-13T11:02:05.590 回答
2

MVarman 的答案适用于 OP,但存在潜在风险,因为AsyncStateMachineAttribute可以手动添加。为了使检查更加健壮,请验证状态机是否是编译器生成的。

public static bool IsAsync(this MethodInfo m)
{
    var stateMachineAttr = m.GetCustomAttribute<AsyncStateMachineAttribute>();
    if (stateMachineAttr != null)
    {
        var stateMachineType = stateMachineAttr.StateMachineType;
        if (stateMachineType != null)
        {
            return stateMachineType.GetCustomAttribute<CompilerGeneratedAttribute>() != null;
        }
    }
    return false;
}

对于 .NET 核心应用程序,请使用

public static bool IsAsync(this MethodInfo m)
{
    return m?
        .GetCustomAttribute<AsyncStateMachineAttribute>()?
        .StateMachineType?
        .GetTypeInfo()
        .GetCustomAttribute<CompilerGeneratedAttribute>()
        != null;
}
于 2016-09-12T08:11:56.647 回答
-1

您无法检测到它,也不应该检测到它。标有 async 的方法实际上与任何其他同步方法没有什么不同。您应该定期调用它们。

此外,Begin/EndInvoke 应该解决对其他线程的封送调用问题。如果您需要特定的知识,即您不知道该方法是否应该在此线程上运行,您应该在这些方法上使用您自己的特殊属性而不是 async 关键字,因为它们基本上不会混合在一起。

于 2012-11-01T23:02:21.853 回答