Xamarin中的死锁,表单

webghufk  于 2023-02-20  发布在  其他
关注(0)|答案(2)|浏览(114)

我的Xamarin应用程序有问题。该应用程序使用自定义API到我的网站。我在async/await方法方面没有太多经验。
下面的代码显示了App.xaml.cs:

public partial class App : Application
{
    public static bool IsUserLoggedIn { get; set; }
    public static UserModel currentLoggedInUser { get; set; }

    public static List<ActionTypeModel> listTypes;
    public static List<ActionSubTypeModel> listSubtypes;
    public static List<UserModel> listFriends;
    public static List<List<ActionModel>> listActiveActions;
    public static List<ActionModel> listLastAction;

    public App()
    {
        this.InitializeComponent();

        APIHelper.InitializeClient();

        StartApp().Wait();
    }

    private async Task StartApp()
    {
        //// DEBUG
        //MyAccountStorage.Logout();

        string username = await MyAccountStorage.GetUsername().ConfigureAwait(false);
        string password = await MyAccountStorage.GetPassword().ConfigureAwait(false);
        string user_id = await MyAccountStorage.GetId().ConfigureAwait(false);
        if (username != null && password != null)
        {

            currentLoggedInUser = new UserModel();
            if (user_id != null)
                currentLoggedInUser.user_id = Convert.ToInt32(user_id);
            currentLoggedInUser.username = username;
            currentLoggedInUser.password = password;

            bool isValid = false;
            isValid = await AreCredentialsCorrect(0, currentLoggedInUser.username, currentLoggedInUser.password).ConfigureAwait(false);
            if (isValid)
            {
                IsUserLoggedIn = true;

                await FillLists().ConfigureAwait(false);

                MainPage = new NavigationPage(await MyPage.BuildMyPage().ConfigureAwait(false));
            }
            else
            {
                IsUserLoggedIn = false;

                MainPage = new NavigationPage(await LoginPage.BuildLoginPage().ConfigureAwait(false));
            }

        }
        else
        {
            IsUserLoggedIn = false;

            MainPage = new NavigationPage(await LoginPage.BuildLoginPage().ConfigureAwait(false));
        }
    }

    private async Task FillLists()
    {
        listFriends = await DataControl.GetFriends(App.currentLoggedInUser.user_id, App.currentLoggedInUser.username, App.currentLoggedInUser.password).ConfigureAwait(false);
        if (listFriends == null)
            listFriends = new List<UserModel>();

        listTypes = await DataControl.GetTypes(App.currentLoggedInUser.username, App.currentLoggedInUser.password).ConfigureAwait(false);
        if (listTypes == null)
            listTypes = new List<ActionTypeModel>();

        listActiveActions = new List<List<ActionModel>>();

        for (int i = 0; i < listTypes.Count; i++)
            listActiveActions.Add(await DataControl.GetActiveActions(listTypes[i].action_type_id, currentLoggedInUser.user_id, currentLoggedInUser.username, currentLoggedInUser.password).ConfigureAwait(false));

        listSubtypes = await DataControl.GetSubtypes(App.currentLoggedInUser.username, App.currentLoggedInUser.password).ConfigureAwait(false);
        if (listSubtypes == null)
            listSubtypes = new List<ActionSubTypeModel>();

        listLastAction = await DataControl.GetLastAction(App.currentLoggedInUser.user_id, App.currentLoggedInUser.username, App.currentLoggedInUser.password).ConfigureAwait(false);
        if (listLastAction == null)
            listLastAction = new List<ActionModel>();
    }

    public static async Task<bool> AreCredentialsCorrect(int type, string user, string pass, string nick = "", string email = "")
    {
        List<UserModel> listUsers;

        if (type == 1)
            listUsers = await DataControl.CheckCredentials(1, user, pass, nick, email).ConfigureAwait(false);
        else
            listUsers = await DataControl.CheckCredentials(0, user, pass).ConfigureAwait(false);

        if (listUsers != null)
            if (listUsers.Any())
            {
                currentLoggedInUser = listUsers.First();
                currentLoggedInUser.password = pass;
                return true;
            }

        return false;
    }
}

我在DataControl.cs中有API:

public static async Task<List<UserModel>> CheckCredentials(int type, string username, string pass, string email = "", string nickname = "")
{
    string password = APIHelper.GetHashSha256(pass);

    string url = string.Empty;

    if (type == 0)
        url = APIHelper.ApiClient.BaseAddress + "/account/login.php?username=" + username + "&password=" + password;
    if (type == 1)
    {
        string nick = string.Empty;
        if (string.IsNullOrEmpty(nickname) == false)
            nick = "&nickname=" + nickname;

        url = APIHelper.ApiClient.BaseAddress + "/account/signup.php?username=" + username + "&password=" + password + "&email=" + email + nick;
    }
    if (string.IsNullOrEmpty(url))
        return null;

    using (HttpResponseMessage response = await APIHelper.ApiClient.GetAsync(url).ConfigureAwait(false))
    {
        if (response.IsSuccessStatusCode)
        {
            List<UserModel> listUsers = JsonConvert.DeserializeObject<List<UserModel>>(await response.Content.ReadAsStringAsync().ConfigureAwait(false));

            return listUsers;
        }
        else
            return null;
    }
}

这是async方法中的一个,当我省略ConfigureAwait(false)时,我会遇到死锁,当我将其添加到代码中时,我会遇到错误。
你能帮帮我吗?

fcy6dtqo

fcy6dtqo1#

正如@GSerg已经写过的,你必须重新构造代码。App构造函数必须将MainPage设置为某个页面。那个页面可以是空的,比如说“Loading data”。
然后,您可以启动一个后台任务来检索您需要的数据。
当数据被加载后,你就可以用新加载的数据更新你的页面,但是UI更新总是必须在UI线程上进行,这在所有平台上都是一样的,所以你必须用Device.BeginInvokeOnMainThread(...)切换回来。

public App()
{
    InitializeComponent();

    APIHelper.InitializeClient();

    MainPage = new LoadingPage();

    // start a background thread
    Task.Run(async () =>
    {
        try
        {
            await StartApp();  // load the data

            // go back to the main thread
            Device.BeginInvokeOnMainThread(() =>
            {
                // replace the MainPage with one which shows the loaded data
                MainPage = new DataPage();
            });
        }
        catch (Exception ex)
        {
            // handle the exception
        }
    });
}
hfwmuf9z

hfwmuf9z2#

您可以使用Task.Run( //call your async method here );
所以在你的例子中:

Task.Run(Startup);

相关问题