此平台不支持操作 - 示例

问题描述

这是来自 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

PlatformNotSupportedException with fetcher at runtime.

解决方法

该项目使用 .NET Core 3.1,但 BeginInvokeEndInvoke 调用 are not supported in .NET Core

The Asynchronous Programming Model (APM)(使用 IAsyncResultBeginInvoke)不再是进行异步调用的首选方法。从 .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) 是一个用户定义的委托。

这样做的原因是用户定义的委托类型上的 BeginInvokeEndInvoke 方法实际上并未在 .NET Framework 库中定义。相反,这些方法由编译器发出(参见 Asynchronous Programming Using Delegates 中的“重要”注释),作为声明委托类型的构建代码的一部分。

此外,异常仅在运行时抛出,因此您必须对每个项目进行广泛的测试。