![](/img/trans.png)
[英]Cannot implicitly convert type string to System.Collections.Generic.Dictionary<string,System.Collections.Generic.Dictionary><string,object>>
[英]Cannot convert from 'System.Threading.Tasks.Task' to 'System.Collections.Generic.Dictionary<string,string>'
我相信我可能只是語法錯誤,但是我想做的是創建一個在另一個任務完成后運行的任務。
我對列表中的100個數組有一個任務。 它啟動一個新線程,將該數組傳遞給方法。 該方法完成后將返回字典。 我正在嘗試創建一個方法完成后要運行的任務,該任務將返回的字典傳遞給執行更多工作的單獨方法。
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);
}
}
如果您已經在使用await
我建議不要使用ContinueWith
。 原因是您最終在代碼中出現的冗長。
相反,請盡可能使用await
。 代碼最終如下所示:
var historicalGroups = symbolList
.Select((x, i) => new { x, i })
.GroupBy(x => x.i / 100)
.Select(g => g.Select(x => x.x).ToArray());
var historicalTasks = historicalGroups.Select(x => Task.Run(() =>
Downloads.getHistoricalStockData(x, market)))
.ToArray();
var historcalStockResults = await Task.WhenAll(historicalTasks);
foreach (var dictionary in historcalStockResults)
{
Downloads.updateSymbolsInDB(dictionary);
}
注意使用Task.Run
代替Task.Factory.StartNew
。 您應該改用它。 在這里更多
編輯:
如果您需要每24小時執行一次此代碼,請添加Task.Delay
並await
它:
await Task.Delay(TimeSpan.FromHours(24));
編輯2:
您的代碼無法正常工作的原因是因為startDownload
為async void
,並且您沒有等待它。 因此while
無論您的Task.Delay
如何,您的while
循環都會保持迭代。
因為您在控制台應用程序內部,所以無法await
因為Main
方法不能異步。 因此,要解決此問題, startDownload
更改為async Task
而不是async void
,然后Wait
返回的Task
。 請注意, 幾乎不應該使用Wait
,除非有特殊情況(例如在控制台應用程序中運行時):
public async Task StartDownload()
接着
while (true)
{
StartDownload().Wait();
}
還要注意,混合Parallel.Foreach
和async-await
並非總是最好的主意。 您可以在Parallel.ForEach中的嵌套等待中了解更多信息。
您會看到ContinueWith將Task作為參數。
此外,通過仔細閱讀我們注釋中的邏輯,您似乎需要更新代碼。 您試圖對所有WhenAll
任務的結果運行一次Downloads.updateSymbolsInDB
。 就您而言,您似乎需要
await Task<Dictionary<string, string>>
.WhenAll(historicalGroups.Select(g => Task.Factory.StartNew(() => Downloads.getHistoricalStockData(g, market))))
.ContinueWith((i) => Downloads.updateSymbolsInDB(i.Result.Aggregate((agg, next) =>
{
foreach (var p in next)
{
if (!agg.ContainsKey(p.Key)) { agg.Add(p.Key, p.Value); }
}
return agg;
})));
請注意,我還使用Task<TResult>
進行初始化,因此對ContinueWith
進行了強類型化,以提供Dictionary<string, string>
i.Result
。
另請注意,您將需要重新i.Result.Aggregate
邏輯中的操作。 您需要對其進行更新以使其正確無誤。 此外,值得回顧一下多次調用Downloads.updateSymbolsInDB
是否更有效,或者Aggregate
調用是否是更好的選擇。
(最后一點:最終結果是void
,因此未分配等待。)
在審查中,您的代碼存在許多問題(僅作為陳述,不是指責-並非故意犯罪)。 通過Task.Factory.StartNew
為WhenAll
方法創建的任務沒有返回值,因此只是基本的Task
對象,實際上正在丟棄Downloads.getHistoricalStockData
工作的結果。 然后,您的ContinueWith
需要與WhenAll
的Task<TResult>
WhenAll
,其中TResult
將是WhenAll
中每個任務的返回值的WhenAll
。
編輯:如被問到如果要多次調用Downloads.updateSymbolsInDB
,如何更新代碼,可以簡單地通過以下方式完成:
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());
Parallel.ForEach(historicalGroups, g => Downloads.updateSymbolsInDB(Downloads.getHistoricalStockData(g, market)));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.