c# - 等待带有动态参数的方法时抛出异常(有时)

标签 c# .net c#-4.0 dynamic task-parallel-library

我有以下代码:

string commandText = await _client
       .GetCommandTextAsync("Products", x.ProductName == "Chai");

第二个参数 (x.ProductName == "Chai") 包含一个动态子句 (x.ProductName),因此生成的表达式也是动态的。这段代码在.NET 4.0 上执行时,有时会抛出如下异常:

System.InvalidCastException Unable to cast object of type 'System.Runtime.CompilerServices.TaskAwaiter`1[System.String]' to type 'System.Runtime.CompilerServices.INotifyCompletion'.

如果我显式地将方法结果传递给任务,则不会抛出异常:

string commandText = await (Task<string>)_client
       .GetCommandTextAsync("Products", x.ProductName == "Chai");

是否有更优雅的方法来解决此问题(无需强制转换等待动态结果的每一行代码),或者这是在 .NET 4.0 上使用 TPL 的已知问题。

我在 .NET 4.5 上没有遇到过这种情况。

最佳答案

这是一个理论:

根据TaskAwaiter定义:

[HostProtectionAttribute(SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
public struct TaskAwaiter : ICriticalNotifyCompletion, INotifyCompletion

TaskAwaiter 似乎是一个INotifyCompletion。你说你的代码中有 dynamic 子句。正如 MS 所述,动态 对象大多表现得像对象。因此,在由运行时或编译器处理的代码中需要强制转换。

您还表示该平台是 Xamarin iOS。例如,可能利用 HostProtectionAttribute 来阻止某些类等的使用。

TaskAwaiter 实现被标记为 SecurityAction.LinkDemand,如果我们再次检查 MSDN它说:

...
LinkDemand (do not use in the .NET Framework 4)
...

因此结论是:运行代码的平台缺乏主机保护所需的安全实现,并且未调用方法(而安全性未正常工作)转换是“安全”操作之一,因此这种类型的运行时转换失败.

如果您像以前那样显式转换,则没有问题,因为编译器不会添加“错误”代码。

关于c# - 等待带有动态参数的方法时抛出异常(有时),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23033731/

相关文章:

c# - 使用新文件更新文件

C#方法通用params参数错误?

c# - Roslyn 代码分析从无错误解决方案中返回错误的构建错误

.net - 无法加载文件或程序集系统找不到指定的文件

c# - .NET 类库项目中的多个 App.Config 文件

xml - 如何阅读 Twitter 提要

c# - 如何按文件名顺序合并文件

c# - Roslyn CTP 是否仍可用于 Visual Studio 2010 SP1

c# - 阻止访问构造函数/仅特定类可以访问

c# - 在计算机休眠或 sleep 后恢复后,在 WPF 中使用什么事件来更新应用程序?