我有一些嵌套的異步方法互相調用,它很混亂。我正試圖轉換一個下載異步下載文件的項目。 下載按鈕的點擊,這是觸發方法:嵌套的異步下載 - 異步內的異步
private async void enableOfflineModeToolStripMenuItem_Click(object sender, EventArgs e)
{
for(int i = 0; i < _playlists.Count; i++)
{
DoubleDimList.Add(new List<String>());
for(int j = 0; j < 5; j++)
{
string sMp3 = IniReadValue(_playlists[i], "Track " + j);
DoubleDimList[i].Add(sMp3);
}
await Task.Run(() => _InetGetHTMLSearchAsyncs(DoubleDimList[i]));
}
}
它創建了一個2d List
其在最後看起來像這樣DoubleDimList[3][20]
。 在每個sublist
的末尾,我正在做一個async
下載,如你所見。該方法是這樣的
private async Task _InetGetHTMLSearchAsyncs(List<string> urlList)
{
foreach (var url in urlList)
{
await Task.Run(() => _InetGetHTMLSearchAsync(url));
}
}
的_InetGetHTMLSearchAsync
方法是這樣的,在這裏是它得到棘手
private async Task _InetGetHTMLSearchAsync(string sTitle)
{
Runs++;
if (AudioDumpQuery == string.Empty)
{
//return string.Empty;
}
string sResearchURL = "http://www.audiodump.biz/music.html?" + AudioDumpQuery + sTitle.Replace(" ", "+");
try
{
using (var client = new WebClient())
{
client.Headers.Add("Referer", @"http://www.audiodump.com/");
client.Headers.Add("user-agent", "Mozilla/5.0(Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14(KHTML, like Gecko) Version/7.0.3 Safari/7046A194A");
client.DownloadStringCompleted += Client_DownloadStringCompleted;
await Task.Run(() => client.DownloadStringAsync(new Uri(sResearchURL)));
}
}
catch (Exception ex)
{
Console.WriteLine("Debug message: " + ex.Message + "InnerEx: " + ex.StackTrace);
Console.WriteLine("Runs: " + Runs);
return;
}
}
在Client_DownloadStringCompleted
還有另一種方法async
叫。這裏是
private async void Client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
string[] sStringArray;
string aRet = e.Result;
string[] aTable = _StringBetween(aRet, "<BR><table", "table><BR>", RegexOptions.Singleline);
if (aTable != null)
{
string[] aInfos = _StringBetween(aTable[0], ". <a href=\"", "<a href=\"");
if (aInfos != null)
{
for (int i = 0; i < 1; i++)
{
sStringArray = aInfos[i].Split('*');
sStringArray[0] = sStringArray[0].Replace("'", "'");
aLinks.Add(sStringArray[0]);
}
await Task.Run(() => DownloadFile(aLinks[FilesDownloaded]));
}
}
}
從那裏,驚喜!撥打另一個async
。
private async Task DownloadFile(string url)
{
try
{
using (var client = new WebClient())
{
client.Headers.Add("Referer", @"http://www.audiodump.biz/");
client.Headers.Add("user-agent", "Mozilla/5.0(Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14(KHTML, like Gecko) Version/7.0.3 Safari/7046A194A");
client.DownloadFileCompleted += Client_DownloadFileCompleted;
await Task.Run(() => client.DownloadFileTaskAsync(url, mp3Path + "\\" + count + ".mp3"));
}
}
catch (Exception Ex)
{
Console.WriteLine("File download error: " + Ex.StackTrace);
}
}
現在創建2d List
後,第一部分是檢索的MP3下載鏈接。第二部分是在提供有效的URL
後立即下載mp3。它的工作原理是奇怪的。它通常不會下載文件(第1,第2,第3 ...),它會隨機下載文件(第1,第5,第8 ...)。
這是我第一次去async
下載和男孩,我已經遠離我的極限了。
我在哪裏搞砸了?主要問題是,它會按照它應該工作的方式工作嗎?
有太多的代碼在這裏,仍然不夠。請提供一個很好的[mcve],可以可靠地再現您的問題。同時,我會指出使用'Task.Run()'執行'async'方法通常毫無意義。只需直接調用'async'方法並'等待'返回的'Task'對象。您可以通過將返回的「Task」表示爲某個「IEnumerable」來收集一組'async'調用,然後使用'await Task.WhenAll(...)'等待整個集合。 –
如果您更仔細地研究'async' /'await'的現有引用並使用好的習語,那麼我敢打賭,你的問題將會消失。總之,請注意,如果您異步執行多個操作,那麼完全按照與啓動時不同的順序完成並不奇怪。如果你使用異步操作,否則,你可能只是一次一個地同步執行它們。 –
你不需要將你的異步方法包裝在Task.Run中。這不是必需的,它會讓你的代碼更難閱讀。您可以等待任務返回異步方法。執行順序不同的原因也是因爲您在啓動下載的Task.Run中觸發了下載。然後該方法返回並開始下一次下載。完成的事件被激發的順序取決於請求時間本身。如果你真的想保持順序,你應該使用DownloadStringTaskAsync,而這會返回一個任務,你可以等待結果。 –