在使用ContinueWith或委托运行某个任务后,不运行RunOnUiThread

时间:2016-09-25 12:05:50

标签: c# delegates xamarin.android async-await task-parallel-library

我想在运行Task(从API获取一些数据)之后在UI线程中更改我的UI元素(隐藏进度条并为listview分配数据)。我没有找到API的问题,在所有情况下都返回数据。有时在运行Task之后执行代码(在RunOnUiThread中)变得没有响应,尤其是当我在调试模式下运行没有任何断点的代码时。当我在调用Task并继续运行之前捕获断点时,一切正常。

protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            _userData = ServiceLocator.GetService<IAuthService>().GetUserData();
            _wallsViewPresenter = ViewPresenterHelper.CreateViewPresenter<WallViewPresenter, IWallView, WallActivity>(this);
            _listView = FindViewById<ListView>(Resource.Id.postList);

            progressBar = FindViewById<ProgressBar>(Resource.Id.progressBar1);
            Task.Run(async () => {
                profile = await _wallsViewPresenter.GetProfile(int.Parse(_userData.Profile));
                WallModel wall = SerializationService.DeSerialize<WallModel>(profile.Wall);
                _posts = (List<PostModel>) (wall.Posts.ToList());                        
            }).ContinueWith(ar =>
            {
                RunOnUiThread(() => {
                    progressBar.Visibility = ViewStates.Gone;
                    _postListAdapter = new PostListAdapter(this, _posts);
                    _listView.Adapter = _postListAdapter;
                    SetListViewHeader();
                    _listView.AddHeaderView(_header);
                    FindViewById<TextView>(Resource.Id.details).Text = profile.Name;
                });
            });               
        }

带委托的版本:

        protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        _userData = ServiceLocator.GetService<IAuthService>().GetUserData();
        _wallsViewPresenter = ViewPresenterHelper.CreateViewPresenter<WallViewPresenter, IWallView, WallActivity>(this);
        _listView = FindViewById<ListView>(Resource.Id.postList);
        progressBar = FindViewById<ProgressBar>(Resource.Id.progressBar1);
        Task.Run(async () => {
            profile = await _wallsViewPresenter.GetProfile(int.Parse(_userData.Profile));
            WallModel wall = SerializationService.DeSerialize<WallModel>(profile.Wall);
            _posts = (List<PostModel>) (wall.Posts.ToList());
            if (_posts.Count != 0)
            {
                DataPopulated?.Invoke(this, true);
            }
        });
        DataPopulated += (sender, e) => {
            RunOnUiThread(() => {
                progressBar.Visibility = ViewStates.Gone;
                _postListAdapter = new PostListAdapter(this, _posts);
                _listView.Adapter = _postListAdapter;
                SetListViewHeader();
                _listView.AddHeaderView(_header);
                FindViewById<TextView>(Resource.Id.details).Text = profile.Name;
            });
        };
    }

1 个答案:

答案 0 :(得分:0)

ContinueWith是一个非常危险的低级API;不应该在这里使用。此外,使用async / await时,无需RunOnUIThread

由于您调用的方法已经异步,因此Task.Run也可能是不必要的。

简化版:

protected override async void OnCreate(Bundle savedInstanceState)
{
  base.OnCreate(savedInstanceState);
  _userData = ServiceLocator.GetService<IAuthService>().GetUserData();
  _wallsViewPresenter = ViewPresenterHelper.CreateViewPresenter<WallViewPresenter, IWallView, WallActivity>(this);
  _listView = FindViewById<ListView>(Resource.Id.postList);

  progressBar = FindViewById<ProgressBar>(Resource.Id.progressBar1);
  profile = await _wallsViewPresenter.GetProfile(int.Parse(_userData.Profile));
  WallModel wall = SerializationService.DeSerialize<WallModel>(profile.Wall);
  _posts = (List<PostModel>) (wall.Posts.ToList());                        

  progressBar.Visibility = ViewStates.Gone;
  _postListAdapter = new PostListAdapter(this, _posts);
  _listView.Adapter = _postListAdapter;
  SetListViewHeader();
  _listView.AddHeaderView(_header);
  FindViewById<TextView>(Resource.Id.details).Text = profile.Name;
}