簡體   English   中英

C#Xamarin表單-執行任務,超時

[英]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.DelayTask.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這是使用WhenAnyDelay效率較低的版本。

方法4:可以接受。 盡管您確實必須處理TaskCompletionSource<T>及其怪癖(例如,默認情況下為同步連續)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM