- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我想在 MonoTouch 应用程序中异步访问 DropBox API。
我认为使用 DropNet 会很方便它本身依赖于 RestSharp .
这两个库都运行良好,但返回 Task
的 DropNet 重载不会为您提供将请求与取消 token 相关联的方法。
这是他们的实现方式:
public Task<IRestResponse> GetThumbnailTask(string path, ThumbnailSize size)
{
if (!path.StartsWith("/")) path = "/" + path;
var request = _requestHelper.CreateThumbnailRequest(path, size, Root);
return ExecuteTask(ApiType.Content, request, cancel);
}
ExecuteTask
实现基于 TaskCompletionSource
和 was原本 written by Laurent Kempé :
public static class RestClientExtensions
{
public static Task<TResult> ExecuteTask<TResult>(
this IRestClient client, IRestRequest request
) where TResult : new()
{
var tcs = new TaskCompletionSource<TResult>();
WaitCallback asyncWork = _ => {
try {
client.ExecuteAsync<TResult>(request,
(response, asynchandle) => {
if (response.StatusCode != HttpStatusCode.OK) {
tcs.SetException(new DropboxException(response));
} else {
tcs.SetResult(response.Data);
}
}
);
} catch (Exception exc) {
tcs.SetException(exc);
}
};
return ExecuteTask(asyncWork, tcs);
}
public static Task<IRestResponse> ExecuteTask(
this IRestClient client, IRestRequest request
)
{
var tcs = new TaskCompletionSource<IRestResponse>();
WaitCallback asyncWork = _ => {
try {
client.ExecuteAsync(request,
(response, asynchandle) => {
if (response.StatusCode != HttpStatusCode.OK) {
tcs.SetException(new DropboxException(response));
} else {
tcs.SetResult(response);
}
}
);
} catch (Exception exc) {
tcs.SetException(exc);
}
};
return ExecuteTask(asyncWork, tcs);
}
private static Task<TResult> ExecuteTask<TResult>(
WaitCallback asyncWork, TaskCompletionSource<TResult> tcs
)
{
ThreadPool.QueueUserWorkItem(asyncWork);
return tcs.Task;
}
}
如何更改或扩展此代码以支持使用 CancellationToken
取消?
我想这样调用它:
var task = dropbox.GetThumbnailTask(
"/test.jpg", ThumbnailSize.ExtraLarge2, _token
);
最佳答案
因为 CancellationToken
是一个值类型,我们可以将它作为可选参数添加到具有默认值的 API 中,避免空检查,这很不错。
public Task<IRestResponse> GetThumbnailTask(
string path, ThumbnailSize size, CancellationToken cancel = default(CancellationToken)
) {
if (!path.StartsWith("/")) path = "/" + path;
var request = _requestHelper.CreateThumbnailRequest(path, size, Root);
return ExecuteTask(ApiType.Content, request, cancel);
}
现在,RestSharp ExecuteAsync
方法返回封装底层 HttpWebRequest
的 RestRequestAsyncHandle
,以及 Abort
方法。这就是我们取消事情的方式。
public static Task<TResult> ExecuteTask<TResult>(
this IRestClient client, IRestRequest request, CancellationToken cancel = default(CancellationToken)
) where TResult : new()
{
var tcs = new TaskCompletionSource<TResult>();
try {
var async = client.ExecuteAsync<TResult>(request, (response, _) => {
if (cancel.IsCancellationRequested || response == null)
return;
if (response.StatusCode != HttpStatusCode.OK) {
tcs.TrySetException(new DropboxException(response));
} else {
tcs.TrySetResult(response.Data);
}
});
cancel.Register(() => {
async.Abort();
tcs.TrySetCanceled();
});
} catch (Exception ex) {
tcs.TrySetException(ex);
}
return tcs.Task;
}
public static Task<IRestResponse> ExecuteTask(this IRestClient client, IRestRequest request, CancellationToken cancel = default(CancellationToken))
{
var tcs = new TaskCompletionSource<IRestResponse>();
try {
var async = client.ExecuteAsync<IRestResponse>(request, (response, _) => {
if (cancel.IsCancellationRequested || response == null)
return;
if (response.StatusCode != HttpStatusCode.OK) {
tcs.TrySetException(new DropboxException(response));
} else {
tcs.TrySetResult(response);
}
});
cancel.Register(() => {
async.Abort();
tcs.TrySetCanceled();
});
} catch (Exception ex) {
tcs.TrySetException(ex);
}
return tcs.Task;
}
最后,Lauren's implementation将请求放入线程池,但我看不出这样做的理由——ExecuteAsync
本身是异步的。所以我不会那样做。
这就是取消 DropNet 操作。
我还做了一些可能对您有用的调整。
因为我无法在不求助于将 ExecuteTask
调用包装到另一个 Task
的情况下安排 DropBox Task
,所以我决定找一个请求的最佳并发级别,对我来说是 4
,并明确设置它:
static readonly Uri DropboxContentHost = new Uri("https://api-content.dropbox.com");
static DropboxService()
{
var point = ServicePointManager.FindServicePoint(DropboxContentHost);
point.ConnectionLimit = 4;
}
我也满足于让未处理的任务异常在 hell 中腐烂,所以这就是我所做的:
TaskScheduler.UnobservedTaskException += (sender, e) => {
e.SetObserved();
};
最后一个观察是,您不应该对 DropNet
返回的任务调用 Start()
,因为该任务会立即开始。如果您不喜欢那样,则需要将 ExecuteTask
包装在另一个不受 TaskCompletionSource
支持的“真实”任务中。
关于c# - 如何在 DropNet 中实现 CancellationToken 支持?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13346912/
原因是如果它是CancellationToken.None,我需要添加一个超时(所以一个新的CancellationToken 来自CancellationTokenSource),例如 if (ca
我认为 RunAsync 方法采用 CancellationToken 作为参数,这很棒。 不幸的是,根据我的观察,我从未被取消。 当然,取消RunAsync 方法并调用OnCloseAsync 会有
我正在尝试使用取消标记从另一个线程中跳出循环: using System; using System.Threading; using System.Threading.Tasks; namespac
我对 AzureFunctions 还很陌生,所以请原谅我问一个简单的问题...... 我有以下代码,当队列中有一个项目时会触发该代码 [FunctionName("ProcessCompanies"
我有以下异步函数: private async Task ValidateFtpAsync() { return await Task.Run( ()
.NET 中的 TPL 新手。尝试了解 CancellationToken 以及它们如何收到取消正在执行的任务的信号。下面的代码只传输一个被取消的任务,因为相同的 token 被传递给两个任务。我的假
我有一个计时器,每 2 秒启动 2 个任务...我在一个简单的列表中跟踪这些任务(这样我就可以在停止应用程序时等待它们完成)。 任务有效地转到数据库,运行几个更新并完成。 任务本身的运行时间不会超过一
在没有搭建快速测试台的情况下;我想我会很快问 SO 看看是否有人知道这个答案。 此外,它可能还有一个额外的好处,即通知可能遇到类似情况的其他用户。 假设我有一个长期存在的 CancellationTo
我的 Xamarin.Forms 项目出现以下错误: at System.Threading.CancellationToken.ThrowOperationCanceledException (
我对如何为以下情况实现取消 token 感到有些困惑。 假设我有一个方法,它有一个取消 token ,没有像这样指定超时。 public static async Task DoSomeAsyncTh
.NET 4.5.1:看来,我无法使用 CancellationTokenSource 内置超时取消在任务中运行的阻塞方法。 class Program { static void Main(
我想使用锁或类似的同步来保护临界区。同时我想听一个CancellationToken。 现在我正在使用这样的互斥锁,但互斥锁的性能不佳。我可以使用任何其他同步类(包括新的 .Net 4.0)来代替互斥
这是我的情况: private CancellationTokenSource cancellationTokenSource; private CancellationToken c
我有一个用于各种任务的 token ,我需要更好地管理它们的取消,以便收到我可以使用的取消通知: token.Register(RegisterMethod); 我怎样才能删除这个“订阅”?有什么办法
我启动一个任务,然后启动其他任务等等。给定那棵树,如果任何任务失败,则整个操作的结果都是无用的。我正在考虑使用取消 token 。令我惊讶的是, token 没有“CancelThisToken()”
我今天早上一直在研究 Async CTP,并且有一个带有 button 和 label 的简单程序。单击按钮,它开始更新标签,停止按钮,它停止写入标签。但是,我不确定如何重置 Cancellation
我有一些异步代码,我想将其添加到 CancellationToken 中。但是,有很多实现不需要这样做,所以我想要一个默认参数 - 也许是 CancellationToken.None。然而, Tas
这段代码执行时 cancellationToken.ThrowIfCancellationRequested(); try catch block 不处理异常。 public Enumerab
最近我遇到了a Microsoft interface使用一个非常不寻常的 API: public interface IHostApplicationLifetime { public Ca
CancellationToken.CanBeCanceled 上的文档描述了它的作用,但没有提到它什么时候可能是假的。因此,我不完全清楚何时应该注意此属性。 在什么情况下它可以是假的,我应该什么时候
我是一名优秀的程序员,十分优秀!