正在从异步操作中将数据封送回UI线程

本文关键字:UI 线程 数据 异步操作 | 更新日期: 2023-09-27 18:21:13

我有一个ICommand,它需要将数据设置为UI线程上的属性。

public override async void Execute(object parameter)
{
    var vm = (MyVm)parameter;
    var data = await _myDataService.GetData();
    vm.MyData = data; // must be set on UI Thread due to binding.
}

现在我想把我的调用封装在一个事件记录器中(我本来想做AOP并用logging属性装饰这个方法,但我在PCL中无法实现)。所以我就这样结束了我的通话。

public override void Execute(object parameter)
{
    EventLogger.LogEvent(this,
        EventLogEntryType.Command,
        EventLogErrorSeverity.Warning,
        Errors.GetServiceAreaCommand_ErrorMessage,
        async () =>
        {
            var vm = (MyVm)parameter;
            var data = await _myDataService.GetData();
            vm.MyData = data; // must be set on UI Thread due to binding.
        });
}

这是LogEvent方法。

public static void LogEvent(object sender,
    EventLogEntryType entryType,
    EventLogErrorSeverity eventLogErrorSeverity,
    string friendlyErrorMessage,
    Action action)
{
    var name = sender.GetType().Name.SplitCamelCase();
    var startEntry = new EventLogEntry(entryType);
    LogEvent(string.Format("Start: {0}", name), startEntry);
    try
    {
        action.Invoke();
    }
    catch (Exception ex)
    {
        var exEntry = new EventLogEntry(EventLogEntryType.Error, friendlyErrorMessage, false, ex)
        {
            ErrorSeverity = eventLogErrorSeverity
        };
        LogEvent(string.Format("Error: {0}", name), exEntry);
        if (eventLogErrorSeverity == EventLogErrorSeverity.Critical)
        {
            throw;
        }
    }
    var endEntry = new EventLogEntry(entryType);
    LogEvent(string.Format("Finish: {0}", name), endEntry);
}

问题是,我似乎仍在后台线程而不是主线程上设置属性(Android中为IllegalStateException)

在将Action封装在日志记录方法中的同时,设置数据的最干净方法是什么?


我也成功地为ICommand创建了一个基类,但它a)更改了CanExecuteExecute的方法签名,B)它也(显然)没有将其功能扩展到Commands之外。

我正在寻找一种干净的方法来记录方法(BeforeExecute,AfterExecute,OnError),无论它们做什么


顺便说一句,理想的日志记录机制是使用Interceptor,但我的C#能力不够强,无法实现它

[Log(EventLogEntryType.Command, EventLogErrorSeverity.Warning, "Some Friendly Message")]
public override async void Execute(object parameter)
{
    var vm = (MyVm)parameter;
    var data = await _myDataService.GetData();
    vm.MyData = data; // must be set on UI Thread due to binding.
}

正在从异步操作中将数据封送回UI线程

如果您可以(下面的警告)访问代码中的Activity对象,那么您可能可以这样做;

Activity.RunOnUiThread(() => {
    //Execute my code on UIThread here
});

但如果,这是一个,因为我注意到你正在使用PCL,或者已经引用了使用PCL的内容,所以我怀疑共享库不会知道任何关于"活动"的信息(除非你也通过了)。这在很大程度上取决于你的应用程序结构和代码所在的位置,但在主要的Xamarin.Android项目中,你的视图如上所述,应该可以使用