You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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异步接口:

  1. 将方法返回类型从Task<BackgroundTaskRegistration>改为IAsyncOperation<BackgroundTaskRegistration>
  2. 使用AsyncInfo.Run包裹所有异步代码,这个方法会自动把.NET异步逻辑转换成WinRT兼容的异步接口
  3. 原有业务逻辑完全保留,只需要调整异步方法的包装方式

修改后的完整代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:12:49