我开发了一个小客户端(WPF)来对我们的系统进行一些压力测试。本质上,它必须并行地调用Asp.Net WebApi端点上的各种方法。
每次按下"Start“,它都会生成4000个任务(异步等待),同时请求压力,等待直到它们全部完成,然后再这样做-直到用户单击停止按钮。GUI使用进度条和一些计数器进行修饰:错误的请求、已完成的请求、正在进行的请求。我获得这些信息是因为发出一批压力请求的对象公开了一些事件:
var stressTestTask = new stressTestTask(LogService, configuration);
stressTestTask.ErrorRequestCountChanged += stressTestTask_ErrorRequestCountChanged;
stressTestTask.GoodRequestCountChanged += stressTestTask_GoodRequestCountChanged;
stressTestTask.TryRequestCountChanged += stressTestTask_TryRequestCountChanged;
_executionCancellationToken = new CancellationTokenSource();
await Task.Run(
() => stressTestTask.ApiStressTestTask(_executionCancellationToken.Token),
_executionCancellationToken.Token);
整个执行是从一个ICommand
(MVVM)开始的:
private RelayCommand _startCommand;
public RelayCommand StartCommand
{
get
{
return _startCommand ?? (_startCommand = new RelayCommand(
async () =>
{
await StartStressTest();
}));
}
}
RelayCommand
是库Mvvm-Light
中ICommand
的一个实现。
我不明白的是这种行为:如果我用“低”数量的任务配置我的批任务,例如2000年,GUI在执行时不会冻结。如果我选择5000项任务,过一段时间它就会结冰。如果打开客户端的.exe的另一个实例,并在每个实例上选择2000,则GUI在这两个方面都具有响应性。
我的第一个问题是:为什么用x
任务打开一个实例在响应性方面比用x/n
任务打开n
实例更糟糕?这是否与Windows Scheduler有关,以及在第一种情况下,我只有一个进程?
我的第二个问题是:如何解决这个问题,使一切都在一个GUI上工作?我考虑用一批压力测试创建一个控制台应用程序,并从GUI中为我想要的每个实例调用一个命令,以便为每个批生成一个进程。
发布于 2016-12-14 02:43:48
您是否通过调用UI上下文来处理这些API事件?如果有许多调用发生,您将向调度程序注入大量操作,并导致UI挂起并落后于用户输入。
尝试批量更新UI。
发布于 2016-12-14 04:50:07
我的第一个问题是:为什么用x任务打开一个实例比用x/n任务打开n个实例更糟糕?
可能是因为在UI线程上要处理更多的事件。我想您的ErrorBetCountChanged、GoodRequestCountChanged和TryRequestCountChanged事件处理程序是在UI线程上调用的,引发的许多事件可能会淹没UI线程。
作为Gusdor sugget,您可能会找到一种批量更新的方法。看看反应性扩展(Rx):WhyRx.html。
它有一个可能派上用场的缓冲区方法:TimeShiftedSequences.html。
它还有en Obervable.FromEvent方法,您可以使用它将事件转换为IObservable:https://msdn.microsoft.com/en-us/library/hh229241(v=vs.103).aspx。
我的第二个问题是:如何解决这个问题,使一切都在一个GUI上工作?
您需要找到一种方法-一种或指定者-更新UI的频率较低。批处理更新和事件应该是一个很好的起点。另一种选择是增加较少的通知。也许你需要两者兼得。
发布于 2016-12-14 02:57:02
我如何解决这个问题,使一切都在一个GUI上工作呢?
以“适当的”异步方式发送API请求--等待方式只有一个线程。
private async Task SendStressRequests()
{
var tasks = new List<Task>();
for (int i = 0; i < 4000; i++)
{
var task = SendApiRequestAsync();
tasks.Add(task);
}
await Task.WhenAll(tasks);
// Update UI with results
}
https://stackoverflow.com/questions/41140414
复制相似问题