![](/img/trans.png)
[英]MySqlConnector 'Connect Timeout Expired' Xamarin Forms and c#
[英]C# Xamarin Forms - Executing task, with timeout
像許多其他應用程序一樣,我需要編寫一個返回任務的函數,並且希望該任務在一定時間后自動超時。
初始代碼如下所示:
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是最“輕量級”的(需要最少的系統資源)?
還有其他方法可以設置我錯過的超時時間嗎?
PS
我發現了一個困難的知識-如果您從主UI線程之外的線程調用GetDataFromServer():
Task.Run(() => await GetDataFromServer());
在iOS上,第四個方法(Xamarin.Forms.Device.StartTimer)從不觸發
我認為只使用Task.Delay
和Task.WhenAny
更容易:
public async Task<string> GetDataFromServerAsync(int timeoutInSeconds)
{
Task<string> requestTask = GetDataFromServerAsync();
var timeoutTask = Task.Delay(timeoutInSeconds);
var completedTask = await Task.WhenAny(requestTask, timeoutTask);
if (completedTask == timeoutTask)
throw new OperationCanceledException();
return await requestTask;
}
其他方法的缺點:
方法1:無緣無故創建一個新的CancellationToken
。 這只是方法2的低效率版本。
方法2:通常,任務完成后,您應該處置Register
的結果。 在這種情況下,由於CTS總是最終被取消,因此可能工作正常。
方法3:僅使用StartNew
來調用Delay
不確定那里的原因。 從本質WhenAny
這是使用WhenAny
的Delay
效率較低的版本。
方法4:可以接受。 盡管您確實必須處理TaskCompletionSource<T>
及其怪癖(例如,默認情況下為同步連續)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.