基本上我需要使用供应商的.Net SDK提供远程请求以获取一些信息。他们的SDK在他们的方法上没有异步实现,所以我试图自己想出一些东西。我基本上想要将此请求发送到同步方法,并等待它只有一定的时间。如果请求耗时太长,我需要采取行动并在我们的网络应用程序中向客户报告。
我想知道这是否是最好的方法,还是有更好的方法?下面的代码是一个从Controller操作调用的服务方法。
{{1}}
答案 0 :(得分:0)
Task.Wait
有一个重载,需要int
来定义超时。
public Task<bool> SignersAdded(string packageId)
{
var timeout = 5000;
var task = Task.Run(() =>
{
var package = _eslClient.GetPackage(new PackageId(packageId));
return package != null && package.Documents.Values.Any(x => x.Signatures.Any());
});
if(!task.Wait(1000 /*timeout*/))
{
// timeout
return false;
}
return task.Result;
}
答案 1 :(得分:0)
您的方法对任何内容都不while
,因此它会同步运行。此外,您的Delay
循环将旋转CPU,阻止调用代码,直到任务完成。
更好的方法可能就是:
TimeSpan
这样我们就可以创建一个单独的延迟任务,我们等待第一个任务完成。这将以一种真正的异步方式运行 - 没有try
{
DateTime.Now.ToString(tmpFormatSpec);
}
catch (Exception)
{
// the format spec is known to be bad
}
循环会烧掉CPU周期。
(上面假设超时是以毫秒为单位。如果没有,则使用重载DateTime.Now.ToString("bla"); // no exception raised
取代{{1}}参数。)
答案 2 :(得分:0)
你是对的:启动一个调用GetPackage的任务。之后你可以继续做其他事情。
过了一段时间,当您需要结果时,您可以等待任务完成。但是你不必做Task.Wait。使用async / await要容易得多。
要做到这一点,你必须做三件事:
<TResult
&gt;。你已经做到了。你的功能看起来会简单得多:
public **async** Task<bool> SignersAdded(string packageId)
{
var timeout = TimeSpan.FromSeconds(5);
var task = Task.Run(() =>
{
var package = _eslClient.GetPackage(new PackageId(packageId));
return package != null
&& package.Documents.Values
.Any(x => x.Signatures.Any());
});
// if desired you can do other things here
// once you need the answer start waiting for it and return the result:
return await Task;
}
如果你有一个返回TResult的函数,它的异步版本会返回Task
<TResult
&gt ;.等待任务
<TResult
&gt;的返回值是TResult
但是,如果您希望能够等待超时,则可以执行以下操作:
var tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(1);
// cancel after 1 second
try
{
return await task.Run( () => ..., tokenSource.Token);
}
catch (OperationCanceledException exc)
{
// handle timeout
}
finally
{
// do necessary cleanup
}
使您的函数异步的缺点是所有调用者也必须是异步的,并且所有调用者都必须返回Task或Task <TResult
&gt;。有一个例外:
事件处理程序可以是异步但可能返回void
示例:
private async void OnButton1_clicked(object sender, )
答案 3 :(得分:0)
查看TaskCompletionSource和CancellationToken类。此处的示例为:Timeout an async method implemented with TaskCompletionSource或How to cancel a TaskCompletionSource using a timout