问题描述
这是来自 Microsoft WPF 示例。可以在 git 上找到源代码为 UsingDispatcher。 它包含在一个包含大量示例的 zip 文件中。
它有点写在这里。我在 MSDN 的其他地方看到过(例如 Threading Model)。
我在错误下方添加了注释掉的行。它工作正常。不过,为什么会出现错误?
private void ForecastButtonHandler(object sender,RoutedEventArgs e)
{
// Change the status image and start the rotation animation.
fetchButton.IsEnabled = false;
fetchButton.Content = "Contacting Server";
weatherText.Text = "";
_hideWeatherImageStoryboard.Begin(this);
// Start fetching the weather forecast asynchronously.
var fetcher = new NoArgDelegate(FetchWeatherFromServer);
fetcher.BeginInvoke(null,null);
//dispatcher.BeginInvoke(dispatcherPriority.normal,fetcher);
}
我在运行时得到一个 PlatformNotSupportedException
。
解决方法
该项目使用 .NET Core 3.1,但 BeginInvoke
和 EndInvoke
调用 are not supported in .NET Core。
The Asynchronous Programming Model (APM)(使用 IAsyncResult
和 BeginInvoke
)不再是进行异步调用的首选方法。从 .NET Framework 4.5 开始,Task-based Asynchronous Pattern (TAP) 是推荐的异步模型。因此,并且因为异步委托的实现依赖于 .NET Core 中不存在的远程处理功能,.NET Core 中不支持 BeginInvoke 和 EndInvoke 委托调用。这在 GitHub 问题 dotnet/corefx #5940 中进行了讨论。
在 .NET Core 中使用 BeginInvoke
会在运行时产生 System.PlatformNotSupportedException
。它适用于 Dispatcher
的原因是它是通过 WPF 移植到 .NET Core 的,所以我想它不会破坏移植到 .NET Core 的现有代码。另一个问题是样本为何包含此错误。链接文章中还描述了一个原因。 .NET Portability Analyzer 没有捕捉到这个和这个,因为 fetcher
(NoArgDelegate
) 是一个用户定义的委托。
这样做的原因是用户定义的委托类型上的 BeginInvoke
和 EndInvoke
方法实际上并未在 .NET Framework 库中定义。相反,这些方法由编译器发出(参见 Asynchronous Programming Using Delegates 中的“重要”注释),作为声明委托类型的构建代码的一部分。
此外,异常仅在运行时抛出,因此您必须对每个项目进行广泛的测试。