在我的代码中,我有一个名为“ShowMessageBoxAsync”的任务。我想使用此代码向用户显示(并等待) DisplayAlert 并返回结果。像这样: var messageBoxResult = wait View.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;
}
在添加 Device.BeginInvokeOnMainThread 之前,该任务给了我一个异常,它没有在主/UI 线程上运行。所以添加BeginInvokeOnMainThread后,就开始工作了,没有异常。但问题是,代码直接转到结果,而不等待“await DisplayAlert”的结果。
是否可以仅在 Device.BeginInvokeOnMainThread 代码完成后返回“result”值?
我对此做了一些研究,有人建议使用 TaskCompletionSource,但这会阻塞 UI 线程,并且 DisplayAlert 根本不会显示。
我对此做了一些研究,有人建议使用 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;
}
这应该可以让你暂时解除封锁。然而,更好的长期解决方案是让后台线程逻辑采用某种“与 UI 交互”界面,如下所示:
public interface IAskUser
{
Task<bool> AskUserAsync(string message);
}
具有与上面类似的 Xamarin-Forms 特定实现。
这样,您的后台线程逻辑就不会与特定的 UI 绑定,并且可以更轻松地进行单元测试和重用。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)