【发布时间】:2017-08-05 04:19:20
【问题描述】:
像许多其他人一样,我需要编写一个返回任务的函数,并且我希望该任务在一段时间后自动超时。
初始代码如下所示:
class MyClass
{
TaskCompletionSource<string> m_source;
public Task<string> GetDataFromServer()
{
m_source = new TaskCompletionSource<string> ();
// System call I have no visibility into, and that doesn't inherently take any
// sort of timeout or cancellation token
ask_server_for_data_and_when_youve_got_it_call(Callback);
return m_source.Task;
}
protected void Callback(string data);
{
// Got the data!
m_source.TrySetResult(data);
}
}
现在我希望它更聪明一点,并在适当的时候自动超时。我有几种选择:
class MyClass
{
TaskCompletionSource<string> m_source;
public Task<string> GetDataFromServer(int timeoutInSeconds)
{
m_source = new TaskCompletionSource<string> ();
ask_server_for_data_and_when_youve_got_it_call(Callback);
// Method #1 to set up the timeout:
CancellationToken ct = new CancellationToken ();
CancellationTokenSource cts = CancellationTokenSource.CreateLinkedTokenSource (ct);
cts.CancelAfter (timeoutInSeconds * 1000);
cts.Token.Register(() => m_source.TrySetCancelled());
// Method #2 to set up the timeout:
CancellationTokenSource ct2 = new CancellationTokenSource ();
ct2.CancelAfter (timeoutInSeconds * 1000);
ct2.Token.Register (() => m_source.TrySetCancelled());
// Method #3 to set up the timeout:
System.Threading.Tasks.Task.Factory.StartNew (async () =>
{
await System.Threading.Tasks.Task.Delay (timeoutInSeconds * 1000);
m_source.TrySetCancelled();
});
// Method #4 to set up the timeout:
Xamarin.Forms.Device.StartTimer (new TimeSpan (0, 0, timeoutInSeconds),
() => m_source.TrySetCancelled());
return m_source.Task;
}
protected void Callback(string data);
{
// Got the data!
m_source.TrySetResult(data);
}
}
设置超时的 4 种不同方式的优缺点是什么?例如,我猜方法 #2 是最“轻量级”的(需要最少的系统资源)?
还有其他方法可以设置我错过的超时吗?
附言
我发现了一条很困难的知识——如果你从主 UI 线程之外的线程调用 GetDataFromServer():
Task.Run(() => await GetDataFromServer());
在 iOS 上,第四种方法 (Xamarin.Forms.Device.StartTimer) 永远不会触发
【问题讨论】:
-
第一个函数是异步的,所以它应该返回字符串,而不是任务。如果您希望此函数返回任务本身,请删除
async关键字 -
我添加了 'await' 功能,这就是我使用 'async' 关键字的原因。
-
但这甚至无法编译...看起来您正在混合同步和异步代码。首先你向服务器发送一个异步请求,然后是一个带有回调的同步请求。带有
public async Task<string>......的函数应该返回一个字符串 -
你是对的,这不是我的实际代码,而只是帮助解释我的问题的示例代码。我已更新代码以删除“异步”。
标签: c# xamarin timeout async-await