取消 taskcompletionsource,它从具有超时 xamarin 形式的 API 调用 void 方法
cancel taskcompletionsource which calls a void method from an API with timeout xamarin forms
我有这个非异步任务>,它只是请求:
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 方法,然后调用一个异步方法,该方法本身调用一个异步方法,该方法对 return 执行异步操作项目列表。
问题是,我无法控制超出上述任务范围的任何事情,因为我刚才解释的所有内容都是 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 架构...
真的,非常感谢您在这件事上的帮助,一切都很好,对于给您带来的不便,我深表歉意...
编辑
抱歉,我没有解释清楚我的 objective;它是:我需要获取访问 API 的项目列表,该 API 仅通过无效方法 FindItemsAsync 与我通信。我有 60 秒的时间来获取所有这些项目。如果出现问题,或者超时,我必须取消进程并通知用户出现问题。
那不会发生。它永远不会取消。要么给我物品,要么永远保持加载状态,尽管我做了最艰难的尝试……我对任务和大部分这些东西都是新手,因此我经常遇到问题……
您可以在取消令牌过期时调用 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<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 方法,然后调用一个异步方法,该方法本身调用一个异步方法,该方法对 return 执行异步操作项目列表。
问题是,我无法控制超出上述任务范围的任何事情,因为我刚才解释的所有内容都是 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 架构...
真的,非常感谢您在这件事上的帮助,一切都很好,对于给您带来的不便,我深表歉意...
编辑
抱歉,我没有解释清楚我的 objective;它是:我需要获取访问 API 的项目列表,该 API 仅通过无效方法 FindItemsAsync 与我通信。我有 60 秒的时间来获取所有这些项目。如果出现问题,或者超时,我必须取消进程并通知用户出现问题。
那不会发生。它永远不会取消。要么给我物品,要么永远保持加载状态,尽管我做了最艰难的尝试……我对任务和大部分这些东西都是新手,因此我经常遇到问题……
您可以在取消令牌过期时调用 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());
}
它将切断连接。