【问题标题】:cancel taskcompletionsource which calls a void method from an API with timeout xamarin forms取消 taskcompletionsource,它从具有超时 xamarin 表单的 API 调用 void 方法
【发布时间】:2016-04-29 10:21:38
【问题描述】:

我有这个非异步任务>,它只是请求:

TaskCompletionSource<ObservableCollection<ItemDto>> tcs = new TaskCompletionSource<ObservableCollection<ItemDto>>();

        ObservableCollection<ItemDto> results = new ObservableCollection<ItemDto>();

        try
        {
            BasicHttpBinding binding = new BasicHttpBinding();
            binding.OpenTimeout = new TimeSpan(0, 0, 30);
            binding.CloseTimeout = new TimeSpan(0, 0, 30);
            binding.SendTimeout = new TimeSpan(0, 0, 30);
            binding.ReceiveTimeout = new TimeSpan(0, 0, 30);

            MobileClient clientMobile = new MobileClient(binding, new EndpointAddress(_endpointUrl));

            clientMobile.FindItemsCompleted += (object sender, FindItemsCompletedEventArgs e) =>
            {
                if (e.Error != null)
                {
                    _error = e.Error.Message;
                    tcs.TrySetException(e.Error);
                }
                else if (e.Cancelled)
                {
                    _error = "Cancelled";
                    tcs.TrySetCanceled();
                }

                if (string.IsNullOrWhiteSpace(_error) && e.Result.Count() > 0)
                {
                    results = SetItemList(e.Result);

                    tcs.TrySetResult(results);
                }
                clientMobile.CloseAsync();
            };
            clientMobile.FindItemsAsync(SetSearchParam(searchString, 100));
        }
        catch (Exception)
        {
            results = new ObservableCollection<ItemDto>();
            tcs.TrySetResult(results);
        }
        return tcs.Task;

是的,我知道,没什么特别的,就是这个

clientMobile.FindItemsAsync(SetSearchParam(searchString, 100))

是对 void 方法的调用,该方法又调用另一个设置一些参数的 void 方法,然后调用异步方法,该方法本身调用异步方法,该方法执行异步操作以返回项目列表。

问题是,我无法控制上述任务范围之外的任何事情,因为我刚刚解释的所有内容都是 API 的一部分,我不能接触其中,也无法发表评论,关于它的工作方式,因为政策是让我的工作适应它...... -_-

因此,为了做到这一点,我必须在总共 1 分钟过去后立即终止对 FindItemsAsync 的调用...我尝试将上述时间跨度设置为每个一分钟(第一次工作,现在进行了一些更改已经完成了,不行),我试着把时间减到一半,不行……

这是调用此任务的代码:

public void LoadItemList(string searchString)
    {
        _itemList = new ObservableCollection<ItemDto>();

        // Calls the Task LoadList.
        var result = LoadList(searchString).Result;

        if (result != null && result != new ObservableCollection<ItemDto>())
        {
            _itemList = result;
        }
        else
        {
            _isTaskCompleted = false;
        }

        _isListEmpty = (_itemList != new ObservableCollection<ItemDto>()) ? false : true;
    }

下面是调用这个任务的调用者的代码......(真是一团糟-_-):

void Init(string searchString = "")
    {
        Device.BeginInvokeOnMainThread(async () =>
        {
            if (!LoadingStackLayout.IsVisible && !LoadingActivityIndicator.IsRunning)
            {
                ToggleDisplayLoadingListView(true);
            }

            await Task.Run(() => _listVM.LoadItemList(searchString));

            ToggleDisplayLoadingListView();

            if (!string.IsNullOrWhiteSpace(_listVM.Error))
            {
                await DisplayAlert("Error", _listVM.Error, "OK");
            }
            else if (_listVM.AdList != null && !_listVM.IsListEmpty)
            {
                ItemListView.IsVisible = true;

                ItemListView.ItemsSource = _listVM.ItemList;
            }
            else if (!_listVM.IsTaskCompleted || _listVM.IsListEmpty)
            {
                await DisplayAlert("", "At the moment it is not possible to show results for your search.", "OK");
            }
            else if (_listVM.ItemList.Count == 0)
            {
                await DisplayAlert("", "At the moment there are no results for your search.", "OK");
            }
        });
    }

目前我正在尝试实现 MVVM 架构...

真的,非常感谢您在这件事上的帮助,这很棒,对于给您带来的所有不便,我深表歉意...

编辑

抱歉,我没有清楚地解释我的目标;它是:我需要获取访问 API 的项目列表,该 API 只是通过 void 方法 FindItemsAsync 与我通信。我有 60 秒的时间来获取所有这些物品。如果出现问题或超时,我必须取消该过程并通知用户出现问题。

这不会发生。它永远不会取消。要么给我物品,要么永远保持加载,尽管我最努力地尝试......我对任务和大部分东西都是新手,因此我经常遇到问题......

【问题讨论】:

    标签: xamarin xamarin.forms timeout cancellationtokensource taskcompletionsource


    【解决方案1】:

    您可以在取消令牌过期时调用 CloseAsync。

    //Creates an object which cancels itself after 5000 ms
    var cancel = new CancellationTokenSource(5000);
    
    //Give "cancel.Token" as a submethod parameter
    public void SomeMethod(CancellationToken cancelToken)
    {
        ...
    
        //Then use the CancellationToken to force close the connection once you created it
        cancelToken.Register(()=> clientMobile.CloseAsync());
    }
    

    它会切断连接。

    【讨论】:

    • 看到问题是我没有取消令牌,甚至不知道如何使用...我所拥有的只是压力,以及永远不够的东西的要求...你会介意解释一下我如何使用该取消令牌,或者如果这个等式缺少什么,请?
    • 你使用了TaskCompletionSource,所以你也应该知道CancellationToken。
    • 对不起,我知道它的存在,但不知道如何使用它,主要是这段代码是从 msdn 示例之一复制的,因为当时我试图等待 API 的结果,并且由于我没有使用任何异步/等待的东西,我在收到结果之前完成了被调用的方法,因此实现了我发现的这个解决方案......
    • 基本上我的所有这些代码都是一团糟,因为它混合了解决我在此过程中遇到的各种问题的解决方案。问题是:我的雇主不喜欢计划做什么的想法(像我这样没有经验的人应该从一开始就做)并且只想要去年的结果,甚至不允许我开始理解我必须完成,更不用说计划我应该完成的每一步,因为那会花费更多的时间...... -_-
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多