【问题标题】:Task async and continuewith任务异步并继续
【发布时间】:2015-10-07 21:42:51
【问题描述】:

我正在尝试从服务器获取数据,然后我需要对这些数据和其他功能做一些事情。

因为我从服务器获取数据,所以我使用 async 和 continuewith 函数来完成。

这是我的代码:

private void login(object sender, EventArgs eventArgs)
{
    SharedFunctions.showHide("Show", pBar, txt);
    result = false;
    if (validateScreen())
    {
        Task task = new Task(() => LoginUser().ContinueWith((t) =>
        {
            afterLogin();
        }));
        task.Start();
    }
}

private void afterLogin()
{
    if (result)
    {
        SharedFunctions.saveDataOnDevice(userID, storeID, permission);

        StartActivity(typeof(SplashScreen));
        Finish();
    }
    else
    {
        SharedFunctions.showHide("Hide", pBar, txt);
        SharedFunctions.showPopUp(this, GetString(Resource.String.error_login), GetString(Resource.String.wrong_name_and_password));
    }
}

private async Task LoginUser()
{
    string userName = uName.Text;
    string password = pass.Text;
    password = SharedFunctions.encrypt(password);

    var client = new RestClient("........");
    string resourceStr = @"api/base/....";
    var request = new RestRequest(Method.POST)
    {
        Resource = resourceStr,
        RequestFormat = DataFormat.Json
    };
    request.AddBody(new { UserName = userName, Password = password });
    var response = await client.ExecuteTaskAsync<dynamic>(request);

    var dt = response.Data;

    if (dt != null)
    {
        userID = dt["ID"];
        storeID = dt["StoreID"];
        permission = dt["Permission"];

        result = true;
    }
    else
        result = false;
}

我的主要问题是,在我得到数据之后,就在这段代码之后:if (dt != null)

当我尝试调试代码时,它到达带有userID = dt["ID"]; 的行,甚至在它执行之前它就跳转到afterLogin() 函数。

在进入下一个之前,我需要对代码进行哪些更改以使其运行整个函数?

提前谢谢你!

【问题讨论】:

  • 调试时抛出异常时如何启用中断。
  • 你为什么用ContinueWith而不是await

标签: c# xamarin async-await


【解决方案1】:

正如我在博客中所描述的,您永远不应该使用 the Task constructorthe Start method。它们是在线程池线程上执行代码的非常过时的方法,您的应用程序甚至不需要这样做,因为LoginUser 是异步的。如果您确实需要在线程池线程上执行代码,正确的 API 是 Task.Run,但在这种情况下您不需要它。

作为旁注,你should not use ContinueWith 在这种情况下,也可以(也在我的博客上解释过)。其实ContinueWith is downright dangerous;你应该改用await

应用这些最佳实践后:

private async void login(object sender, EventArgs eventArgs)
{
  SharedFunctions.showHide("Show", pBar, txt);
  result = false;
  if (validateScreen())
  {
    await LoginUser();
    afterLogin();
  }
}

【讨论】:

    【解决方案2】:

    当它跳出时,意味着任务中断(异常),但它不会破坏整个程序,因为这是一个异步任务。

    在右侧设置断点并检查dt 中的内容。 尤其是像"ID" 这样的字符串,你经常会遇到这样的错误。也可能是 "Id""id" 不等于 nill 但也不匹配您的 "ID"

    祝你好运!

    【讨论】:

      【解决方案3】:

      问题非常不同。

      我发现我无法将动态对象中的 var 转换为 int,这就是程序停止的原因。

      我更改了这一行:userID = dt["ID"];为此: userID = Convert.ChangeType(dt["ID"], typeof(int));

      现在它可以工作了。

      感谢大家提出的所有建议。

      【讨论】:

        【解决方案4】:

        Task.ContinueWith 仅在原始任务完成后启动。 我不确定这是否会帮助你,但试试这个

        private void login(object sender, EventArgs eventArgs)
        {
            SharedFunctions.showHide("Show", pBar, txt);
            result = false;
            if (validateScreen())
            {
                Task.Factory.StartNew(() => { LoginUser(); }).ContinueWith((t) => { afterLogin(); });
            }
        }
        

        并使您的登录成为正常的无效功能。

        【讨论】:

          猜你喜欢
          • 2014-11-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多