내 WPF UI에 고객 목록이 있습니다. 또한 한 고객의 프로필을 가져 오기위한 웹 API 서비스가 있습니다. 서버 쪽과 클라이언트 쪽 모두 async
/await
을 사용하여 만들어졌으며 취소 할 수 있습니다.취소 가능한 요청 스트림에서 단일 비동기 웹 서비스 호출을 반복적으로 사용하는 방법은 무엇입니까?
사용자가 ComboBox에서 "Customer A"를 선택하면 서버 호출이 트리거되어 고객 프로필을 가져옵니다. 2 초 후 (서버 조치 방법의 고안된 기간) 데이터가 리턴되고 표시됩니다. 2 초 동안 "고객 B"가 선택되면 제 코드가 첫 번째 요청을 취소하고 두 번째 요청을 시작합니다.
이 모든 것이 효과적입니다. 사용자가 매우 다른 고객을 신속하게 선택하면 is-busy/cancellation 논리가 상당히 순진하며 제대로 취소되지 않습니다. 예를 들어, 아래쪽 화살표 키 (콤보 상자에 포커스가 있음)를 빠르게 10 번 누르면 5 회의 요청이 서버 측에서 올바르게 취소되고 5 회의 요청이 올바르게 처리되지 않습니다. 이것이 세계의 끝은 아니지만 잠재적으로 큰 데이터베이스 쿼리가 아무 이유없이 병렬로 실행되는 서버 리소스를 씹어서는 안됩니다. 새로운 UI 항목을 선택하면 모든 단일 요청이 취소되는 것을 보장 이런 종류의 일에 대한 몇 가지 잘 구축 된 패턴이 있어야합니다 같은 느낌
CancellationTokenSource _customerProfileCts;
//called when a new customer item is selected from the UI's ComboBox
private async void TriggerGetCustomerProfile()
{
//if there is already a customer profile fetch operation in progress, we just want to cancel it and start a new one.
if (IsBusyFetchingCustomerProfile)
{
_customerProfileCts.Cancel();
}
try
{
IsBusyFetchingCustomerProfile = true;
IsCustomerProfileReady = false;
await GetCustomerProfile();
}
finally
{
IsBusyFetchingCustomerProfile = false;
_customerProfileCts = null;
}
}
private async Task GetCustomerProfile()
{
_customerProfileCts = new CancellationTokenSource();
await _customerSvc.GetCustomerProfileReport(SelectedCustomer.Id, _customerProfileCts.Token);
//logic for checking result of web call and distributing received data omitted
}
:
여기 내 클라이언트 코드 아무리 빨리 사용자가 선택 하든지간에.
실제로 리 액티브 확장 기능의 주요 사용 사례 중 하나가 아닙니까? 키 입력이 텍스트 상자에 입력 된 후 검색 웹 서비스를 호출하는 것과 같은 가설적인 문제에 대한 언급이 많이 있지만 이전에 보낸 요청을 취소하는 예는 발견하지 못했습니다.
나는 이런 종류의 취소 가능한 비동기 가져 오기가 문제가없는 내 응용 프로그램에서 사용할 수 있도록 깨끗하고 단단하고, 잘 포장 된 복잡성을 숨길 수있는 무언가가 필요합니다.
정말 멋졌습니다. 내 'IsBusyFetchingCustomerProfile' 통화 중 표시기가 취소 된 통화의'finally '에서 다시 설정되는 작은 부작용이있었습니다. 새 통화가 높은 값을 설정 한 순간입니다. 당신의'AsyncLock'을 사용하여'try/finally'를 감싸고 문제를 해결했습니다. – BCA