R. *_*ats 3 c# asynchronous async-await xamarin.forms
在我的代码中,我有一个名为“ShowMessageBoxAsync”的任务。我想使用此代码向用户显示(并等待)DisplayAlert 并返回结果。像这样: var messageBoxResult = await View.ShowMessageBoxAsync("这是一个错误");
ShowMessageBoxAsync 的代码是:
public async System.Threading.Tasks.Task<bool> ShowMessageBoxAsync(string message)
{
var result = false;
Device.BeginInvokeOnMainThread(async () =>
{
result = await DisplayAlert("Error", message, "OK", "Cancel");
});
return result;
}
Run Code Online (Sandbox Code Playgroud)
在我添加 Device.BeginInvokeOnMainThread 之前,该任务给了我一个异常,表明它没有在主/UI 线程上运行。所以添加了BeginInvokeOnMainThread后,就开始正常工作了。然而,问题在于代码直接转到结果,而不是等待“await DisplayAlert”的结果。
只有在 Device.BeginInvokeOnMainThread 代码完成后才可能返回“result”的值吗?
我对此做了一些研究,有人建议使用 TaskCompletionSource,但这会阻止 UI 线程并且 DisplayAlert 根本不显示。
Ste*_*ary 12
我做了一些研究,有人建议使用 TaskCompletionSource
那是正确的解决方案。TaskCompletionSource充当Task. 在这种情况下,这Task是代表用户交互,因此您希望 UI 线程上的代码完成Task,而后台线程上的代码 (a) 等待 `Task.
所以,像这样:
public Task<bool> ShowMessageBoxAsync(string message)
{
var tcs = new TaskCompletionSource<bool>();
Device.BeginInvokeOnMainThread(async () =>
{
try
{
var result = await DisplayAlert("Error", message, "OK", "Cancel");
tcs.TrySetResult(result);
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
});
return tcs.Task;
}
Run Code Online (Sandbox Code Playgroud)
这应该可以让你暂时解锁。但是,更好的长期解决方案是让您的后台线程逻辑采用某种“与 UI 交互”的界面,如下所示:
public interface IAskUser
{
Task<bool> AskUserAsync(string message);
}
Run Code Online (Sandbox Code Playgroud)
具有与上述类似的 Xamarin-Forms 特定实现。
这样,您的后台线程逻辑就不会绑定到特定的 UI,并且可以更轻松地进行单元测试和重用。
这个问题现在值得更新 - 在最新版本的 Xamarin Forms 中,现在有一个名为 awaitable 的方法Device.InvokeOnMainThreadAsync,在我看来,它比其他答案更易于使用且不那么冗长。
var result = false;
await Device.InvokeOnMainThreadAsync(async () =>
{
result = await DisplayAlert("Error", message, "OK", "Cancel");
});
return result;
Run Code Online (Sandbox Code Playgroud)
或者,如果您不是在 Xamarin 表单中运行,您也可以从 Xamarin.iOS、Xamarin.Android 或 Xamarin.UWP 引用 Xamarin.Essentials 并像这样调用 MainThread 扩展
var result = false;
await MainThread.InvokeOnMainThreadAsync(async () =>
{
result = await DisplayAlert("Error", message, "OK", "Cancel");
})
return result;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3227 次 |
| 最近记录: |