我正在创建一个通用加载程序,我想启动一个HttpClient SendAsync请求。但是,其中一些请求可能需要时间,因此我希望添加取消选项,并在完成后通知。
这似乎是一个标准的场景-- imho。
我不确定这是否是正确的方法,但根据我看过的一些例子,这是我的立场。如果您查看代码的底部,我的问题是--在这一点上,是否检查响应并引发成功或错误事件?
public bool StartFetch()
{
if (IsFetching) return false;
IsFetching = true;
mCancellationTokenSource = new CancellationTokenSource();
// this is not awaited, so execution should continue
StartTask(request, mCancellationTokenSource.Token);
return true;
}
public bool CancelFetch()
{
// send cancellation
if (mCancellationTokenSource != null)
mCancellationTokenSource.Cancel();
Cleanup();
return true;
}
private async Task StartTask(LFHttpRequest request, CancellationToken cancellationToken)
{
var message = new HttpRequestMessage(request.Method, request.Uri);
var response = await HttpClient.SendAsync(message, cancellationToken);
// at this point, do I take a look at response and raise a custom OnSuccess or OnError event???
// or do I want to grab the task from `SendAsync`, check for completed or faulted?
}发布于 2013-12-13 00:14:44
当您查看与任务相关的状态(如IsFetching )时,只公开Task本身通常更干净、更容易。
就像这样:
public Task<T> FetchTask { get; private set; }
public bool StartFetch()
{
if (FetchTask != null) return false;
mCancellationTokenSource = new CancellationTokenSource();
FetchTask = FetchAsync(request, mCancellationTokenSource.Token);
return true;
}
public bool CancelFetch()
{
// send cancellation
if (mCancellationTokenSource != null)
mCancellationTokenSource.Cancel();
FetchTask = null;
return true;
}
private async Task<T> FetchAsync(LFHttpRequest request, CancellationToken cancellationToken)
{
var message = new HttpRequestMessage(request.Method, request.Uri);
var response = await HttpClient.SendAsync(message, cancellationToken);
response.EnsureSuccessStatusCode();
var ret = // Convert response.Content into T.
return ret;
}发布于 2013-12-12 22:49:02
如果InvalidOperationException状态无效,建议为StartFetch和CancelFetch操作抛出IsFetching s。这可能看起来很烦人,但它让您在程序员错误和线程问题成为一个更大、更隐蔽的问题之前就可以捕捉到它们。
至于异步方法,您的方法应该返回一个结果。所以也许类似于private async Task<MyHttpResult> StartTask(...)。您的结果应该包含确定成功、失败和取消的方法。
例如:
public sealed class MyHttpResult
{
public HttpResponse Result { get; private set; }
public Exception Error { get; private set; }
public bool WasCancelled { get; private set; }
public MyHttpResult(HttpResponse result, Exception error, bool wasCancelled)
{
this.Result = result;
this.Error = error;
this.WasCancelled = wasCancelled;
}
}如果取消了许多异步方法,它们将抛出一个TaskCanceledException,因此您可以使用catch来表示它,如下所示:
async Task<MyHttpResult> StartTask(LFHttpRequest request, CancellationToken cancellationToken)
{
var message = new HttpRequestMessage(new HttpMethod(request.Method), request.Uri);
HttpResponse response = null;
Exception lastError = null;
bool wasCancelled = false;
try
{
response = await MessageInvoker.SendAsync(message, cancellationToken);
}
catch(TaskCanceledException)
{
wasCancelled = true;
}
catch(Exception ex)
{
lastError = ex;
}
var result = new MyHttpResult(response, lastError, wasCancelled);
return result;
}这都是假设您的观察者也是调用者,所以他们可以await这个方法。如果不是这样的话,您对EventHandler的想法是有意义的。您可以创建如下所示的自定义EventArgs类,而不是返回结果:
public delegate void TaskResultEventHandler<T>(object sender, TaskResultEventArgs<T> e);
public sealed class TaskResultEventArgs<T> : EventArgs
{
public T Result { get; private set; }
public Exception Error { get; private set; }
public bool WasCancelled { get; private set; }
public TaskResultEventArgs(T result, Exception error, bool wasCancelled)
{
this.Result = result;
this.Error = error;
this.WasCancelled = wasCancelled;
}
}然后,这只是一个公开一个TaskResultEventHandler<HttpResponse>和您的观察者订阅它的问题。您可以这样调用它:
var handler = this.HttpTaskCompleted;
if(handler != null)
handler(this, new TaskResultEventArgs<HttpResponse>(response, lastError, wasCancelled));发布于 2013-12-14 17:14:53
在你等待http电话之后
var response = await HttpClient.SendAsync(message, cancellationToken); 您应测试是否取消:
if(cancellationToken.IsCancellationRequested)
//... do what you want, throw or return false or null, depending on how you want to handle this cancellation.或者您可以在一个调用中检查并抛出Microsoft异常:
cancel.ThrowIfCancellationRequested();https://stackoverflow.com/questions/20555683
复制相似问题