这个问题有一个解决方法,只需使用
.Result
并使其同步,但我认为应该有一种正确的方法可以使用ListenableFuture在.NET MAUI中执行异步代码。
上下文:所以我正在制作一个定期运行的 Worker。它可能会调用
async
方法,例如从 Internet 获取结果。 Android 文档建议使用 ListenableWorker,this SO 答案 也是如此。然而,MAUI/Xamarin 的“翻译”非常奇怪,我无法真正让它工作。
这是Android的代码:
public class CallbackWorker extends ListenableWorker {
public CallbackWorker(Context context, WorkerParameters params) {
super(context, params);
}
@NonNull
@Override
public ListenableFuture<Result> startWork() {
return CallbackToFutureAdapter.getFuture(completer -> {
Callback callback = new Callback() {
int successes = 0;
@Override
public void onFailure(Call call, IOException e) {
completer.setException(e);
}
@Override
public void onResponse(Call call, Response response) {
successes++;
if (successes == 100) {
completer.set(Result.success());
}
}
};
for (int i = 0; i < 100; i++) {
downloadAsynchronously("https://www.example.com", callback);
}
return callback;
});
}
}
这是 Xamarin 的等效项,但签名似乎并不相同:
public class TestTask : ListenableWorker
{
public TestTask(Context appContext, WorkerParameters workerParams) : base(appContext, workerParams)
{
}
public override IListenableFuture StartWork()
{
return CallbackToFutureAdapter.GetFuture(new FutureCallback());
}
class FutureCallback : Java.Lang.Object, CallbackToFutureAdapter.IResolver
{
public Java.Lang.Object? AttachCompleter(CallbackToFutureAdapter.Completer p0)
{
// What is Callback here?
// What do I put in here?
// I want to do something like this:
// await DoSomethingAsync();
// Done
}
}
}
请告诉我如何在 .NET MAUI 中实现文档示例。
编辑:在尝试探索 API 时,我意识到他们确实有一个方便的扩展方法
GetAsync
,相反(Android IListenableFuture
-> .NET Task
),因此必须有一些简单的方法来转换我不知道的其他方式?例如:
var existingWorks = await man.GetWorkInfosByTag(WorkerTag).GetAsync() as IEnumerable<WorkInfo>;
if (existingWorks?.Any() == true) { return; }
你可以让你的类继承类
ListenableWorker
并实现接口CallbackToFutureAdapter.IResolver
请参考以下代码:
public class SimpleListenableWorker : ListenableWorker, CallbackToFutureAdapter.IResolver
{
public const string TAG = "SimpleListenableWorker";
public SimpleListenableWorker(Context context, WorkerParameters workerParams) :
base(context, workerParams)
{
}
public override IListenableFuture StartWork()
{
Log.Debug(TAG, "Started.");
return CallbackToFutureAdapter.GetFuture(this);
}
public Object AttachCompleter(CallbackToFutureAdapter.Completer p0)
{
Log.Debug(TAG, $"Executing.");
//Switch to background thread.
Task.Run(async () =>
{
//Perform a process here, simulated by a delay for 5 seconds.
var delaySeconds = 5;
var progress = 0;
var progressIncrement = 100 / delaySeconds;
var dataBuilder = new Data.Builder();
for (int i = 0; i < delaySeconds+1; i++)
{
await Task.Delay(1000);
progress += progressIncrement;
dataBuilder.PutInt("Progress", progress);
SetProgressAsync(dataBuilder.Build());
}
Log.Debug(TAG, "Completed.");
//Set a Success Result on the completer and return it.
return p0.Set(Result.InvokeSuccess());
});
return TAG;
}
}
有关更多信息,您可以参考文章在 XAMARIN ANDROID 中使用 WORKMANAGER 和 LISTENABLEWORKER。