Blazor - 如何从非 UI 组件在 UI 调度程序线程上启动任务?

用户2209634

我正在使用 Xamarin Mobile Blazor Bindings 开发 Android/iOS 位置跟踪器应用程序。我不认为我特别使用 Xamarin Mobile Blazor 绑定这一事实是相关的,但我提到它是为了完整性。

该应用每 15 秒轮询一次移动设备的当前 GPS 位置,并在收到新位置时调用自定义事件,通知任何已注册该事件的 Blazor UI 组件。

所有 GPS 逻辑和事件处理都在一个简单的(非 UI)单例类中完成,如下所示:

public class MyLocationManager
{
    public event EventHandler<LocationUpdatedEventArgs> OnLocationUpdateReceived;

    private Timer _timer;

    public void StartLocationTracking()
    {
        if (DeviceInfo.Platform == DevicePlatform.Android)
        {
            // On Android, Location can be polled using a timer
            _timer = new Timer(
                async stateInfo =>
                {
                    var newLocationCoordinates = await _addCurrentLocationPoint();  

                    var eventArgs = new LocationUpdatedEventArgs
                    {
                       Latitude = newLocationCoordinates.Latitude,
                       Longitude = newLocationCoordinates.Longitude
                    };

                    // **** The following line generates an Exception ****
                    OnLocationUpdateReceived?.Invoke(this, eventArgs)
                },
                new AutoResetEvent(false),
                15000 /* Wait 15 seconds before initial call */,
                15000 /* Then repeat every 15 seconds */
            );
        }
    }
}

不幸的是,当定时器触发时,以下代码会产生异常:

OnLocationUpdateReceived?.Invoke(this, eventArgs)

例外是:

System.InvalidOperationException: '当前线程与 Dispatcher 无关。触发渲染或组件状态时,使用 InvokeAsync() 将执行切换到 Dispatcher。

现在,我明白异常在说什么,当前正在运行的非 UI 线程不能用于调用事件,所以我需要以某种方式使用 Dispatcher 线程。

但是,提到的“InvokeAsync()”方法似乎只存在于 UI 组件的基类中,而“MyLocationManager”类不存在。

任何人都可以就我如何从诸如此类的非 UI 类中实现相同的目标提供任何建议吗?

感激地收到任何建议。

尼古拉·比亚达

您是否尝试过通过组件上的状态处理程序使用 InvokeAsync?您可以使用这种方法,而不是在管理器上使用它:如何修复“当前线程与渲染器的同步上下文无关”?

实际上,您注册更改处理程序事件并在组件端执行 InvokeAsync:

    private async void OnMyChangeHandler(object sender, EventArgs e)
    {
        // InvokeAsync is inherited, it syncs the call back to the render thread
        await InvokeAsync(() => {
            DoStuff();
            StateHasChanged());
        }
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章