【问题标题】:Deadlock in Xamarin.FormsXamarin.Forms 中的死锁
【发布时间】:2020-06-06 21:56:34
【问题描述】:

我的 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) 时,我遇到了死锁。当我将它添加到代码中时,我遇到了错误。

你能帮帮我吗?

【问题讨论】:

  • When I leave out the "ConfigureAwait(false)" I run into a deadlock - 这强烈表明你在某个地方是blocking on async。例如在您的constructor 中的StartApp().Wait();。不要这样做。
  • App 构造函数是我使用 Wait() 方法的唯一位置。其他所有方法都是异步的,并使用 await 来调用。
  • 是的,一个就够了。
  • 如果我删除 Wait() 应用程序什么也不做,我在调试输出中看到一个无穷无尽的线程池启动行和线程池完成...
  • 您不能使用构造函数中的异步函数。您不仅需要删除Wait(这会导致fire-and-forget),还需要重新构建程序,以免从构造函数中调用异步方法。

标签: c# xamarin asynchronous xamarin.forms async-await


【解决方案1】:

您可以使用Task.Run( //call your async method here );

所以在你的情况下:

 Task.Run(Startup);

【讨论】:

    猜你喜欢
    • 2014-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多