0

I have this task I need to timeout, and which is supposed to receive results form a SOAP service within 60 seconds.

The idea is: «SOAP, you've got 60 seconds to get me the results; either they're here in time, or I won't be able to receive them and will have to alert the user, something went wrong.»

Very easy in English, but I've tried a few options in c# and no go... :s

So far I tried:

task.Wait(60000);
Task.Delay(60000);
Device.StartTimer(TimeSpan.FromMinutes(1), () => { tcs.TrySetResults(results); return true; });

And we're still nothing. Either it waits the whole 60 seconds, or if something goes wrong it never stops...

I'm new to this kind of operations, so I know it's really likely I'm doing something really foolish, or laking something really simple, but either way I'm lost...

I'm using c# in Xamarin Forms.

Any help, please?

Thanks in advance.

EDIT: Code form the soap request.

ObservableCollection<ItemDto> LoadList(string searchString)
{
    TaskCompletionSource<ObservableCollection<ItemDto>> tcs = new TaskCompletionSource<ObservableCollection<ItemDto>>();

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

    try
    {
        MobileClient clientMobile = new MobileClient(new BasicHttpBinding(), new EndpointAddress(_endpointUrl));

        clientMobile.FindItemsCompleted += (object sender, FindItemsCompletedEventArgs e) =>
        {
            _error = (e.Error != null) ? e.Error.Message : ((e.Cancelled) ? "Cancelled" : string.Empty);

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

                tcs.TrySetResult(results);
            }
        };
        clientMobile.FindItemsAsync(SetSearchParam(searchString, 100));
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Failed to Load List. Ex: {0}", ex.ToString());
        return new ObservableCollection<ItemDto>();
    }
    return tcs.Task.Result;
}

NEW EDIT

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

    var result = LoadList(searchString);

    if (result != null)
    {
        _itemList = result;
    }
    else
    {
        _isTaskCompleted = false;
    }

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

(all the above occurs in ListViewModel)

And now in the view's code behind I call:

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", "Cancel");
        }
        else if (_listVM.ItemList != null && !_listVM.IsListEmpty)
        {
            ItemListView.IsVisible = true;

            ItemListView.ItemsSource = _listVM.ItemList;
        }
        else if (!_listVM.IsTaskCompleted)
        {
            await DisplayAlert("Error", "Task canceled due to timeout", "OK", "Cancel");
        }
        else if (_listVM.ItemList.Count == 0)
        {
            await DisplayAlert("", "For the moment there are no results for this search.", "OK");
        }
    });
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
prosa
  • 79
  • 6
  • 19

1 Answers1

3

As I see, you're using a BasicHTTPClient. You can try this:

BasicHttpBinding myBinding = new BasicHttpBinding();
myBinding.OpenTimeout = new TimeSpan(0, 1, 0);
myBinding.CloseTimeout = new TimeSpan(0, 1, 0);
myBinding.SendTimeout = new TimeSpan(0, 1, 0);
MobileClient clientMobile = new MobileClient(myBinding, new EndpointAddress(_endpointUrl));

On the other hand, you should return a Task> (see this blog for example) in your LoadList method. Then you can start a parallel timer (from another question)

int timeout = 60000;
var task = SomeOperationAsync();
if (await Task.WhenAny(task, Task.Delay(timeout)) == task) {
    // task completed within timeout
} else { 
    // timeout logic
}
Community
  • 1
  • 1
Matt
  • 4,612
  • 1
  • 24
  • 44