问题 使用task.Whenall与超时

BCZM8703.

成员
加入
2014年1月21日
消息
5
编程经验
1-3
我有一个移动应用程序代码,获取远程Web服务的数据。

我已经设置了任务以获取数据并更新各种选项卡中的相应UI元素

这是我当前的代码
C#:
var doughnutData = GetDoughnutDataAsync(filters);
var barData = GetBarDataAsync(filters);
var trendlineData = GetTrendLineDataAsync(filters);
var categoryData = GetCategoryDataAsync(filters);
var clientData = GetClientDataAsync(filters);
await Task.WhenAll(doughnutData, barData, trendlineData, categoryData, clientData);

从上面的代码中,应用程序中有5个任务对应于5个选项卡

虽然任务正在运行,但我将在所有5个标签中显示一个加载图标。完成任务后,将隐藏上述任务的加载图标

一切都在运行良好,但会有随机时间,服务器或其他一些事物导致任务运行很长。

我想要的是,如果未完成任务我想要在相应的选项卡处显示连接问题消息,则需要在2分钟后进行超时。
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,903
地点
切萨皮克,va.
编程经验
10+
快速和肮脏的方式是这样的:
C#:
var timeOut = TimeSpan.FromMinutes(2);
:
var doughnutData = Task.WhenAny(GetDoughnutDataAsync(filters), Task.Delay(timeOut));
: // repeat same pattern above for the other tasks

// then do like you did previously
await Task.WhenAll(doughnutData, barData, trendlineData, categoryData, clientData);

A better way would be to makes sure that you various GetFooDataAsync methods all take a cancellation token parameter. Then you would write something like:
C#:
var timeOut = TimeSpan.FromMinutes(2);
var cancellationTokenSource = new CancellationTokenSource(timeOut);
var token = cancellationTokenSource.Token;
:
var doughnutData = GetDoughnutDataAsync(filters, token);
: // repeat same pattern above for the other tasks

// then do like you did previously
await Task.WhenAll(doughnutData, barData, trendlineData, categoryData, clientData);
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,903
地点
切萨皮克,va.
编程经验
10+
另一个快速和肮脏的变化:
C#:
var timeOut = TimeSpan.FromMinutes(2);
await Task.WhenAny(Task.WhenAll(doughnutData, barData, trendlineData, categoryData, clientData),
                   Task.Delay(timeOut));
 

BCZM8703.

成员
加入
2014年1月21日
消息
5
编程经验
1-3
你好。感谢回复。但我如何知道哪个任务没有成功完成,以便我可以用邮件更新UI元素?

可能发生在超时之前任务Trendlinedata没有完成任务,等等
 

BCZM8703.

成员
加入
2014年1月21日
消息
5
编程经验
1-3
你好。

我尝试过这个,但似乎只完成了甜甜圈任务。剩下的任务似乎是UI元素达到了半路的更新并被中断。

代码
C#:
var timeOut = TimeSpan.FromMinutes(2);

var doughnutData = GetDoughnutDataAsync(filters);
var barData = GetBarDataAsync(filters);
var trendlineData = GetTrendLineDataAsync(filters);
var categoryData = GetCategoryDataAsync(filters);
var clientData = GetClientDataAsync(filters);

var doughnutTask = Task.WhenAny(doughnutData, Task.Delay(timeOut));
var barTask = Task.WhenAny(barData, Task.Delay(timeOut));
var trendlineTask = Task.WhenAny(trendlineData, Task.Delay(timeOut));
var categoryTask = Task.WhenAny(categoryData, Task.Delay(timeOut));
var clientTask = Task.WhenAny(clientData, Task.Delay(timeOut));

await Task.WhenAll(doughnutTask, barTask, trendlineTask, categoryTask, clientTask);


if(!doughnutData.IsCompleted)
{
     doughnutBusyIndicator.IsBusy = false;
     doughnutBusyIndicator.IsVisible = false;
     lblSlaAchivementError.IsVisible = true;
     lblSlaAchivementError.Text = "Connection to server has timeout";
 }

if (!barData.IsCompleted)
{
     barBusyIndicator.IsBusy = false;
     barBusyIndicator.IsVisible = false;
     lblDeliveryError.IsVisible = true;
     lblDeliveryError.Text = "Connection to server has timeout";
 }

if (!trendlineData.IsCompleted)
 {
       trendlineBusyIndicator.IsBusy = false;
       trendlineBusyIndicator.IsVisible = false;
       lblTrendlineError.IsVisible = true;
       lblTrendlineError.Text = "Connection to server has timeout";
}

if (!categoryData.IsCompleted)
{
     categoryBusyIndicator.IsBusy = false;
     categoryBusyIndicator.IsVisible = false;
     lblCategoryError.IsVisible = true;
     lblCategoryError.Text = "Connection to server has timeout";
}

if (!clientData.IsCompleted)
{
       clientBusyIndicator.IsBusy = false;
       clientBusyIndicator.IsVisible = false;
       lblClientDetailError.IsVisible = true;
       lblClientDetailError.Text = "Connection to server has timeout";
}

taskissue.jpg.



任务完成后,将隐藏红色框区域,图表假设要呈现并显示黑框区域。

目前显示了黑盒子区域,但红色框不会消失,图表未显示。
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,903
地点
切萨皮克,va.
编程经验
10+
我可能会从POST#6那样做代码,如:
C#:
class Element
{
    public Task Task;
    public BusyIndicator BusyIndicator;
    public Label Label;

    void ShowTimedOut()
    {
        BusyIndicator.IsBusy = false;
        BusyIndicator.IsVisible = false;
        Label.IsVisible = true;
        Label.Text = "Connection to server has timed out."
    }

    public void Update()
    {
        if (!Task.IsCompleted)
            ShowTimedOut();
    }
}
:

var elements = new List<Element>()
{
    new Element()
    {
        Task = GetDoughnutDataAsync(filters),
        Indicator = doughnutBusyIndicator,
        Label = lblSlaAchievementError
    },
    :
};

var timeOut = TimeSpan.FromMinutes(2);
await Task.WhenAll(elements.Select(e => Task.WhenAny(e.Task, Task.Delay(timeOut))));

foreach(var element in elements)
    element.Update();

Or if I deemed that the ContinueWith() was a non-issue:
C#:
class Element
{
    public Task Task;
    public BusyIndicator BusyIndicator;
    public Label Label;

    public void ShowTimedOut()
    {
        BusyIndicator.IsBusy = false;
        BusyIndicator.IsVisible = false;
        Label.IsVisible = true;
        Label.Text = "Connection to server has timed out."
    }
}
:

var elements = new List<Element>()
{
    new Element()
    {
        Task = GetDoughnutDataAsync(filters),
        Indicator = doughnutBusyIndicator,
        Label = lblSlaAchievementError
    },
    :
};

var timeOut = TimeSpan.FromMinutes(2);
await Task.WhenAll(elements.Select(e => 
                                   Task.WhenAny(e.Task,
                                                Task.Delay(timeOut)
                                                    .ContinueWith(_ => e.ShowTimedOut()))));
 
最佳 底部