Следующий код заменит значения NA в соответствии с тестом Shapiro:
library(dplyr)
data %>%
group_by(sex) %>%
mutate(
emotion = ifelse(!is.na(emotion), emotion,
ifelse(shapiro.test(emotion)$p.value > 0.05,
mean(emotion, na.rm=TRUE), quantile(emotion, na.rm=TRUE, probs=0.5) ) ),
IQ = ifelse(!is.na(IQ), IQ,
ifelse(shapiro.test(IQ)$p.value > 0.05,
mean(IQ, na.rm=TRUE), quantile(IQ, na.rm=TRUE, probs=0.5) )
)
)
Есть два решения. Быстрым и грязным было бы добавить счетчик, чтобы указать количество оставшихся заданий, которое будет увеличиваться, как и до вызова GetResponse
, и уменьшаться в рамках обратного вызова, а если оно достигнет 0, вызовите следующий шаг в вашем процессе. Это было бы рискованно из-за состояния состязания и непредсказуемого поведения потока, например, если вы вызываете один запрос и до того, как начнется второй запрос, а затем он попытается продолжить.
Лучшим решением было бы отслеживать порожденные Задачи, используя OpenReadTaskAsync
вместо OpenReadAsync
, а затем использовать Task.WhenAll({ALL YOUR TASKS})
.
Это немного изменит вашу программу:
List<Result> result = new List<Result>();
List<Task<Stream>> jobs = new List<Task<Stream>>();
...
GetResponse
пришлось бы возвращать значение задачи, которое является простым.
private Task<Stream> GetResponse(Uri uri, Action<MyResponse> callback)
{
... //Almost all of your code stays the same,
//though you should close the stream you receive in the OnReadCompleted callback.
return m_webClient.OpenReadTaskAsync(uri.ToString());
}
Последний в методе FillResults
, вы должны добавить эти задачи в список и ждать.
public async Task FillResults()
{
foreach( var urlx in Urls)
{
jobs.Add(
GetResponse(urlx, (response) =>
{
if (response != null && response.StatusCode==200)
{
Result result=new Result;
result.Value=response.SomeValue;
result.url=urlx;------>It is important that SomeValue corresponds to urlx and not other say,urly
results.Add(result);
}
})
);
}
await Task.WhenAll(jobs);
//Or Task.WhenAll(jobs).ContinueWith({AN ACTION CALLBACK})
//if you want to keep the return as a void;
}
Теперь вы можете либо ожидать функцию FillResults, где бы вы ни вызывали этот метод, либо иметь другой обратный вызов для обработки завершения