像其他人一样,我需要编写一个返回任务的函数,并希望该任务在一定时间后自动超时。
初始代码如下:
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);
}
}
四种设置超时的方法各有利弊。例如,我猜想第二种方法最轻量级(需要最少的系统资源)?
还有其他我可能遗漏的设置超时的方法吗?
p.s.
一个我曾经吃过亏的知识点是 - 如果你从主UI线程以外的线程调用GetDataFromServer()方法:
Task.Run(() => await GetDataFromServer());
在iOS上,第四种方法(Xamarin.Forms.Device.StartTimer)从不触发。
async
关键字。 - Peter Bruinspublic async Task<string>......
的函数应该返回一个字符串。 - Peter Bruins