Reputation: 1463
I download many urls from the web but I don't know when all the urls have been finished to download. Meanwhile I wrote something, but it seem too me a trash although it works.
In my code I download all the urls from dtPP
dataTable and save them to matUrlFharsing
array.
Here is my code:
main()
{
Parallel.For(0, dtPP.Rows.Count, i =>
{
string f = "";
WebClient client = new WebClient();
client.DownloadDataCompleted += new DownloadDataCompletedEventHandler(client_DownloadDataCompleted);
lock (dtPP.Rows[i])
{
f = dtPP.Rows[i]["pp_url"].ToString();
}
client.DownloadDataAsync(new Uri(f), i);
});
while (end)
{
}
DoSomething();
}
void client_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
int h = (int)e.UserState;
page = (int)e.UserState;
myString = enc.GetString(e.Result);
lock (matUrlFharsing[h])
{
lock (dtPP.Rows[h])
{
//save in mat
matUrlFharsing[h] = Pharsing.CreateCorrectHtmlDoc(myString);
}
}
lock (myLocker)
{
ezer = false;
for (int j = 0; j < matUrlFharsing.Length && !ezer; j++)
{
if (matUrlFharsing[j] == "")
ezer = true;
}
end = ezer;
}
}
What can I do to improve or change it?
Upvotes: 2
Views: 449
Reputation: 6301
You can use array of AutoResetEvent, send them to event receiver as parameter and wait them all.
AutoResetEvent[] autoResetEvents;
main()
{
autoResetEvent = new AutoResetEvent[dtPP.Rows.Count];
Parallel.For(0, dtPP.Rows.Count, i =>
{
string f = "";
WebClient client = new WebClient();
client.DownloadDataCompleted += new DownloadDataCompletedEventHandler(client_DownloadDataCompleted);
lock (dtPP.Rows[i])
{
f = dtPP.Rows[i]["pp_url"].ToString();
}
Object[] parameters = new Object[2];
autoResetEvents[i] = new AutoResetEvent(false);
parameters[0] = i;
parameters[1] = autoResetEvent[i];
client.DownloadDataAsync(new Uri(f), parameters);
});
WaitHandle.WaitAll(autoResetEvents);
DoSomething();
}
void client_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
Object[] parameters = (object[])e.UserState;
autoResetEvent = (AutoResetEvent)parameters[1];
int h = (int)parameters[0];
page = (int)e.UserState;
myString = enc.GetString(e.Result);
lock (matUrlFharsing[h])
{
lock (dtPP.Rows[h])
{
//save in mat
matUrlFharsing[h] = Pharsing.CreateCorrectHtmlDoc(myString);
}
}
autoResetEvent.Set();
}
Upvotes: 1
Reputation: 47
The completed event is called when the async function is finished. You are in the right path...
You can improve you code in the While (end). This While statement will run very fast. You can:
Upvotes: 0
Reputation: 6301
Small improvement:
Use AutoResetEvent instead of bool for End.
AutoResetEvent autoResetEvent;
main()
{
autoResetEvent = new AutoResetEvent(false);
Parallel.For(0, dtPP.Rows.Count, i =>
{
// your code
});
autoResetEvent.WaitOne();
DoSomething();
}
void client_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
...
if(ezer)
{
autoResetEvent.Set();
}
}
Upvotes: 4