和其他许多人一样,我需要编写一个返回任务的函数,并且我希望该任务在一段时间后自动超时。
初始代码如下所示:
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 是最“轻量级”的(需要最少的系统资源)?
还有其他方法可以设置我错过的超时吗?
p.s.
我通过艰难的方式发现了一个知识 - 如果您从主 UI 线程之外的线程调用 GetDataFromServer() :
Task.Run(() => await GetDataFromServer());
在 iOS 上,第四种方法 (Xamarin.Forms.Device.StartTimer) 永远不会触发