Impossible de convertir de 'Système.Le filetage.Les tâches.La tâche' de 'Système.Les Collections.Génériques.Dictionnaire<string,string>'
Je crois que j'ai peut-être juste la syntaxe de mal, mais ce que j'essaie de faire est de créer une tâche qui s'exécute après l'autre tâche est terminée.
J'ai une tâche pour chaque tableau de 100 dans une liste. Il démarre un nouveau thread passage que tableau dans une méthode. La méthode retourne un dictionnaire quand il se termine. Je suis en train de créer une tâche à exécuter après la méthode est terminée, où il passe le retour de dictionnaire, à une méthode qui ne un peu plus de travail.
static void Main(string[] args)
{
try
{
stopwatch = new Stopwatch();
stopwatch.Start();
while (true)
{
startDownload();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public static async void startDownload()
{
try
{
DateTime currentDay = DateTime.Now;
if (Helper.holidays.Contains(currentDay) == false)
{
List<string> markets = new List<string>() { "amex", "global", "nasdaq", "nyse" };
Parallel.ForEach(markets, async market =>
{
try
{
IEnumerable<string> symbolList = Helper.getStockSymbols(market);
var historicalGroups = symbolList.Select((x, i) => new { x, i })
.GroupBy(x => x.i / 100)
.Select(g => g.Select(x => x.x).ToArray());
Task<Dictionary<string, string>>[] historicalTasks =
historicalGroups.Select(x => Task.Run(() =>
Downloads.getHistoricalStockData(x, market)))
.ToArray();
Dictionary<string, string>[] historcalStockResults = await
Task.WhenAll(historicalTasks);
foreach (var dictionary in historcalStockResults)
{
Downloads.updateSymbolsInDB(dictionary);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
});
await Task.Delay(TimeSpan.FromHours(24));
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
- Êtes-vous après un tableau de
Task<Dictionary<string, string>>
ou un tableau deDictionary<string, string>
? - Aussi, ce n'
Downloads.updateSymbolsInDB
retour? - public static async Task<Dictionnaire<string, string>> getHistoricalStockData(string[] les symboles, la chaîne de marché) j'ai besoin de passer à la Tâche<Dictionnaire<string, string>>
- Le updateSymbols méthode ressemble à ceci et retourne void public static void updateSymbolsInDB(Dictionnaire<string, string> erreurs)
- Va
updateSymbolsInDB
exécuter pour chaque résultat degetHistoricalStockData
, ou est-il censé exécuter une seule fois sur l'ensemble de tous lesgetHistoricalStockData
résultats? - J'ai essayé de l'exécuter en une seule fois parce que je pensais que ce serait plus efficace
Vous devez vous connecter pour publier un commentaire.
Je vous conseille de ne pas utiliser
ContinueWith
à tous, si vous utilisez déjàawait
. La raison en est le niveau de verbosité vous vous retrouvez avec dans votre code.Au lieu de cela, utiliser
await
lorsque cela est possible.Le code se termine comme ça:
Notez l'utilisation de
Task.Run
au lieu deTask.Factory.StartNew
. Vous devez utiliser à la place. Plus sur que iciEdit:
Si vous avez besoin pour exécuter ce code, une fois toutes les 24 heures, ajouter un
Task.Delay
etawait
sur elle :Edit 2:
La raison que votre code n'est pas le travail, c'est parce que
startDownload
estasync void
, et vous n'êtes pas en attente sur elle. Ainsi, votrewhile
boucle conserve l'itération quel que soit votreTask.Delay
.Parce que vous êtes à l'intérieur d'une Application de Console, vous ne pouvez pas
await
parce queMain
méthodes ne peux pas être asynchrone. Donc, pour contourner ce problème, modifiezstartDownload
êtreasync Task
au lieu deasync void
, etWait
sur ce qui est retournéTask
. Notez que l'utilisation deWait
devrait presque jamais être utilisé, s'attendre pour les scénarios spéciaux (comme lors de l'exécution à l'intérieur d'une application console):et puis
Également noter que le mélange
Parallel.Foreach
etasync-await
n'est pas toujours la meilleure idée. Vous pouvez en lire plus sur que dans L'imbrication attendent en Parallèle.ForEachDownloads.updateSymbolsInDB
appel, vous pouvez remplacer l'foreach
bloc avec laAggregate
logique comme je l'avais inclus dans ma réponse. Mais à nouveau, le profil d'abord pour voir si c'est même bénéfique.Wait
? Si vous avez ce code s'exécutant dans certainswhile
boucle, il suffit d'utiliserawait Task.Delay(TimeSpan.FromHours(24));
async-await
, pas besoin de thread. Si vous êtes de mélange async IO lié travailler avec les CPU de travail, je vous recommande d'utiliser TPL dataflow.Vous verrez que ContinueWith prend comme Tâche comme argument.
Aussi, de travailler par le biais de votre logique dans nos commentaires, il semble que vous devrez mettre à jour votre code. Vous essayez d'exécuter le
Downloads.updateSymbolsInDB
une fois sur le résultat de tous lesWhenAll
les tâches sont terminées. Dans votre cas, il semble que vous aurez besoinNoter que j'ai aussi utilisé la
Task<TResult>
d'initier, de sorte que leContinueWith
est fortement typé pour fournir laDictionary<string, string>
i.Result
.Notez également que vous aurez envie de revoir ce que je fais dans la
i.Result.Aggregate
logique. Vous aurez besoin de mettre à jour que pour être correct pour votre cas. En outre, il peut être intéressant de revoir pour voir si il est plus efficace de simplement appelerDownloads.updateSymbolsInDB
plusieurs fois, ou si leAggregate
appel est le meilleur choix.(Dernière remarque: le résultat de fin est un
void
, de sorte que les attendent n'est pas affecté.)En examen, il y avait un certain nombre de problèmes avec votre code (fait comme une déclaration, pas une accusation - n'en déplaise prévu). Vos tâches créées par le biais de
Task.Factory.StartNew
pour votreWhenAll
méthode n'a pas de valeur de retour, donc de baseTask
objets, et n'étaient en fait que de jeter les résultats de laDownloads.getHistoricalStockData
travail. Ensuite, votreContinueWith
nécessaire pour travailler avec laTask<TResult>
de laWhenAll
, oùTResult
sera un tableau de la valeur de retour de chaque tâche dansWhenAll
.EDIT: Comme l'a demandé comment le code peut être mis à jour si
Downloads.updateSymbolsInDB
devaient être appelée plusieurs fois, il pourrait simplement être fait que: