UWP Windows Runtime Component调用RequestAccessAsync的编译错误解决
解决UWP后台任务注册时的async Task编译错误
看起来你踩了WinRT组件API设计的一个常见坑——在Windows Runtime Component项目里,公共方法不能返回.NET的Task<T>类型,必须使用WinRT原生的异步接口,比如IAsyncOperation<T>,这就是你遇到WME1039错误的核心原因。
问题根源
WinRT组件的公共API需要严格遵循WinRT类型系统规范,.NET Task属于.NET专属类型,无法被WinRT运行时正确识别和跨语言调用。编译器要求你把返回类型替换成WinRT标准的异步接口:无返回值用IAsyncAction,有返回值用IAsyncOperation<T>。
修复步骤
我们只需要调整RegisterBackgroundTask方法的返回类型,并用AsyncInfo.Run包装异步逻辑,就能让它适配WinRT异步接口:
- 将方法返回类型从
Task<BackgroundTaskRegistration>改为IAsyncOperation<BackgroundTaskRegistration> - 使用
AsyncInfo.Run包裹所有异步代码,这个方法会自动把.NET异步逻辑转换成WinRT兼容的异步接口 - 原有业务逻辑完全保留,只需要调整异步方法的包装方式
修改后的完整代码
public sealed class BackgroundTask : IBackgroundTask { private BackgroundTaskDeferral _deferral; private BackgroundTaskCancellationReason _cancelReason = BackgroundTaskCancellationReason.Abort; private volatile bool _cancelRequested = false; public void Run(IBackgroundTaskInstance taskInstance) { taskInstance.Task.Completed += TaskInstance_OnCompleted; taskInstance.Canceled += TaskInstance_OnCanceled; _deferral = taskInstance.GetDeferral(); // TODO: 在这里编写你的异步任务逻辑,记得使用await // await ExampleMethodAsync(); _deferral.Complete(); } // 修改返回类型为WinRT异步接口,并使用AsyncInfo.Run包装逻辑 public static IAsyncOperation<BackgroundTaskRegistration> RegisterBackgroundTask( string taskEntryPoint, string taskName, IBackgroundTrigger trigger, IBackgroundCondition condition) { // 用AsyncInfo.Run包装异步逻辑,生成WinRT兼容的异步接口 return AsyncInfo.Run(async token => { // 检查任务是否已注册 foreach (var cur in BackgroundTaskRegistration.AllTasks) { if (cur.Value.Name == taskName) { return (BackgroundTaskRegistration)cur.Value; } } var builder = new BackgroundTaskBuilder { Name = taskName, TaskEntryPoint = taskEntryPoint }; builder.SetTrigger(trigger); if (condition != null) { builder.AddCondition(condition); } // 正常await权限请求的异步方法 var access = await BackgroundExecutionManager.RequestAccessAsync(); if (access != BackgroundAccessStatus.AlwaysAllowed && access != BackgroundAccessStatus.AllowedSubjectToSystemPolicy) { return default; } var task = builder.Register(); task.Completed += Registered_OnCompleted; return task; }); } private static void Registered_OnCompleted(IBackgroundTaskRegistration task, BackgroundTaskCompletedEventArgs args) { var settings = Windows.Storage.ApplicationData.Current.LocalSettings; var key = task.TaskId.ToString(); if (settings.Values.ContainsKey(key)) { var message = settings.Values[key].ToString(); // UpdateUI(message); } } private void TaskInstance_OnCompleted(BackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs args) { } private void TaskInstance_OnCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason) { _cancelRequested = true; _cancelReason = reason; Debug.WriteLine("Background " + sender.Task.Name + " Cancel Requested..."); } }
额外说明
- 在UWP主项目中调用这个方法时,你依然可以正常使用
await关键字,因为WinRT的异步接口完全支持.NET的awaiter模式 - 如果是无返回值的异步方法,只需把返回类型换成
IAsyncAction,同样用AsyncInfo.Run包装即可
内容的提问来源于stack exchange,提问作者Maximus
相关产品推荐
相关产品推荐

