1

I have this non-async Task> which just requests:

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;

Yes, I know, nothing special, it's just that this

clientMobile.FindItemsAsync(SetSearchParam(searchString, 100))

is a call to a void method, which in turn calls another void method which sets a few params in order to then call an async method which itself calls an async method which performs an async operation to return the list of Items.

Problem is, I have no control whatsoever of anything beyond the scope of this Task above, because everything I just explained is part of an API, in which I'm not allowed to touch, and of which I can make no comment, regarding the way it works, as the policy is for me to adapt my work to it... -_-

So, in order to do that, I must kill this call to the FindItemsAsync, as soon as a total of 1 minute has passed... I tried setting the above timespans to a minute each (first worked, now some changes have been made and no go), I tried reducing to half the time, and no go...

Here's the code which is calling this Task:

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;
    }

and below is the code which calls the caller of this task... (what a mess -_-):

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");
            }
        });
    }

At the moment I'm trying to implement the MVVM arch...

Really, thank you so much for your help on this matter, it's been great, and I really apologize for all this inconvenience...

EDIT

Sorry because I didn't explain my objective clearly; it is: I need to fetch a list of Items accessing an API that just communicates with me via a void method FindItemsAsync. I have 60 seconds to fetch all those items. If something goes wrong, or if timeout, I have to cancel the process and inform the user something went wrong.

That doesn't happen. It never cancels. Either gets me the Items, or stays loading forever, dispite my hardest tries... I'm new to tasks and most of this stuff, hence my constant issues...

Cœur
  • 37,241
  • 25
  • 195
  • 267
prosa
  • 79
  • 6
  • 19

1 Answers1

2

You can call CloseAsync when your cancellation token expires.

//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());
}

It will cut down the connection.

Softlion
  • 12,281
  • 11
  • 58
  • 88
  • see the problem is I have no cancellation token, and wouldn't even know how to use one... all I have is pressure, and requirements of something that is never enough... would you mind explaining a bit more about how I could use that cancellation token, or if it is whats is missing from this equation, please? – prosa Apr 29 '16 at 12:05
  • You used TaskCompletionSource, so you should know about CancellationToken too. – Softlion Apr 29 '16 at 12:21
  • sorry, I know of its existance, but not how to work with it, and mainly this code was copied from one of msdn examples, because back then I was trying to wait for the results from the API, and as I wasn't using any of the async/await stuff, I was finishing the called method before receiving the results, hence implementing this solution which I found... – prosa Apr 29 '16 at 13:22
  • basically all this code of mine is a mess because its a mixture of pieces of solutions for various problems I faced along the way. problem is: my employer doesn't like the idea of planing what to do (which someone as inexperienced as I am should be doing from the start) and just wants results, for last year, not allowing me to even begin to understand what I must accomplish, much less plan every step I should work on, because that would take even more time... -_- – prosa Apr 29 '16 at 13:25