C#Xamarin表单 - 执行任务,超时



像其他许多人一样,我需要编写一个返回任务的函数,我希望该任务在一定时间段内自动超时。

初始代码看起来像这样:

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)从不发射

我认为只使用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-不确定那里的推理。它本质上是具有WhenAnyDelay的效率较低。

方法#4:可以接受。尽管您确实必须处理TaskCompletionSource<T>及其怪癖(例如,默认情况下同步连续性)。

相关内容

  • 没有找到相关文章

最新更新