异步任务取消c#xamarin
我有搜索用户的功能。我提供了一个textview,在这个textview更改的方法上,我启动了一个从web服务器获取数据的方法。但当用户键入字母时,我会遇到问题,因为所有api命中都是在异步任务中完成的。服务应该在100毫秒的等待后被点击,这意味着如果用户键入字母“a”,然后在100毫秒内没有键入,那么我们必须点击服务。但是如果用户输入“a”然后输入“b”然后输入“c”,那么应该为“abc”点击一个服务,而不是为所有服务 我跟踪了官方链接,但对我没有帮助 基本上这是我的代码异步任务取消c#xamarin,c#,xamarin,async-await,C#,Xamarin,Async Await,我有搜索用户的功能。我提供了一个textview,在这个textview更改的方法上,我启动了一个从web服务器获取数据的方法。但当用户键入字母时,我会遇到问题,因为所有api命中都是在异步任务中完成的。服务应该在100毫秒的等待后被点击,这意味着如果用户键入字母“a”,然后在100毫秒内没有键入,那么我们必须点击服务。但是如果用户输入“a”然后输入“b”然后输入“c”,那么应该为“abc”点击一个服务,而不是为所有服务 我跟踪了官方链接,但对我没有帮助 基本上这是我的代码 textview.
textview.TextChange+= (sender,e) =>{
CancellationTokenSource cts = new CancellationTokenSource();
await Task.Delay(500);
// here some where I have to pass cancel token
var lst = await APIClient.Instance.GetUserSearch("/user/get?searchTerm=" + newText, "application/json",cts);
if (lst != null && lst.Count > 0){
lstSearch.AddRange(lst);
}
}
下面是我获取用户的方法
public async Task<JResponse> GetUserSearch<JResponse>(string uri, string contentType,CancellationToken cts)
{
try
{
Console.Error.WriteLine("{0}", RestServiceBaseAddress + uri);
string url = string.Format("{0}{1}", RestServiceBaseAddress, uri);
var request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = contentType;
if (Utility.CurrentUser != null && !string.IsNullOrWhiteSpace(Utility.CurrentUser.AuthToken))
{
request.Headers.Add("api_key", Utility.CurrentUser.AuthToken);
}
request.Method = "POST";
var payload = body.ToString();
request.ContentLength = payload.Length;
byte[] byteArray = Encoding.UTF8.GetBytes(body.ToString());
request.ContentLength = byteArray.Length;
using (var stream = await request.GetRequestStreamAsync())
{
stream.Write(byteArray, 0, byteArray.Length);
stream.Close();
}
using (var webResponse = await request.GetResponseAsync())
{
var response = (HttpWebResponse)webResponse;
using (var reader1 = new StreamReader(response.GetResponseStream()))
{
Console.WriteLine("Finished : {0}", uri);
var responseStr = reader1.ReadToEnd();
var responseObj = JsonConvert.DeserializeObject<JResponse>(
responseStr,
new JsonSerializerSettings()
{
MissingMemberHandling = MissingMemberHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore
});
return responseObj;
}
}
}
catch (System.Exception ex)
{
Utility.ExceptionHandler("APIClient", "ProcessRequestAsync", ex);
}
return default(JResponse);
}
公共异步任务GetUserSearch(字符串uri、字符串contentType、CancellationToken)
{
尝试
{
WriteLine(“{0}”,RestServiceBaseAddress+uri);
stringurl=string.Format(“{0}{1}”,RestServiceBaseAddress,uri);
var request=(HttpWebRequest)WebRequest.Create(url);
request.ContentType=ContentType;
if(Utility.CurrentUser!=null&&!string.IsNullOrWhiteSpace(Utility.CurrentUser.AuthToken))
{
Add(“api_key”,Utility.CurrentUser.AuthToken);
}
request.Method=“POST”;
var payload=body.ToString();
request.ContentLength=有效负载.Length;
byte[]byteArray=Encoding.UTF8.GetBytes(body.ToString());
request.ContentLength=byteArray.Length;
使用(var stream=await request.GetRequestStreamAsync())
{
stream.Write(byteArray,0,byteArray.Length);
stream.Close();
}
使用(var webResponse=await request.GetResponseAsync())
{
var response=(HttpWebResponse)webResponse;
使用(var reader1=newstreamreader(response.GetResponseStream())
{
WriteLine(“完成:{0}”,uri);
var responsest=reader1.ReadToEnd();
var responseObj=JsonConvert.DeserializeObject(
回应者,
新的JsonSerializerSettings()
{
MissingMemberHandling=MissingMemberHandling.Ignore,
NullValueHandling=NullValueHandling.Ignore
});
返回响应bj;
}
}
}
catch(System.Exception-ex)
{
ExceptionHandler(“APIClient”、“ProcessRequestAsync”、ex);
}
返回默认值(JResponse);
}
尝试使用计时器。第一次,然后你改变文本-你创建它。然后,在这之后更改文本-重新启动计时器。如果在700毫秒内不更改文本,计时器将触发PerformeSearch方法。使用Timeout.Infinite作为计时器周期参数,以防止其重新启动
textview.TextChange += (sender,e) =>
{
if (_fieldChangeTimer == null)
_fieldChangeTimer = new Timer(delegate
{
PerformeSearch();
}, null, 700, Timeout.Infinite);
else
{
_fieldChangeTimer.Change(700, Timeout.Infinite);
}
};
在您的示例中,您正在创建一个
CancellationTokenSource
——您需要保留对它的引用,以便下次调用处理程序时,可以取消以前的搜索。是一个示例控制台应用程序,您应该能够运行它,但重要的部分在处理程序中
private CancellationTokenSource _cts;
private async void TextChangedHandler(string text) // async void only for event handlers
{
try
{
_cts?.Cancel(); // cancel previous search
}
catch (ObjectDisposedException) // in case previous search completed
{
}
using (_cts = new CancellationTokenSource())
{
try
{
await Task.Delay(TimeSpan.FromSeconds(1), _cts.Token); // buffer
var users = await _userService.SearchUsersAsync(text, _cts.Token);
Console.WriteLine($"Got users with IDs: {string.Join(", ", users)}");
}
catch (TaskCanceledException) // if the operation is cancelled, do nothing
{
}
}
}
确保将
CancellationToken
传递到所有async
方法中,包括那些执行web请求的方法,这样您就可以将取消信号传递到最低级别。实例化CancellationTokenSource
cts=新的CancellationTokenSource();示例法
你应该调查一下。谢谢你的身体,3小时过去了,2分钟后你的帖子就解决了:)
private void cancelButton_Click(object sender, RoutedEventArgs e)
{
if (cts != null)
{
cts.Cancel();
}
}