2

Webから多くのURLをダウンロードしますが、すべてのURLのダウンロードがいつ終了したかわかりません。その間、私は何かを書きましたが、それは機能しますが、私もゴミのようです。

私のコードでは、dtPPdataTableからすべてのURLをダウンロードし、それらをmatUrlFharsing配列に保存します。

これが私のコードです:

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;
            }
        }

それを改善または変更するにはどうすればよいですか?

4

3 に答える 3

4

小さな改善:

Endにはboolの代わりにAutoResetEventを使用します。

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();
   }

}
于 2012-10-09T13:45:39.467 に答える
1

AutoResetEventの配列を使用して、パラメーターとしてイベントレシーバーに送信し、すべて待機することができます。

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();
    }
于 2012-10-09T14:06:30.730 に答える
0

完了したイベントは、非同期関数が終了したときに呼び出されます。あなたは正しい道を進んでいます...

While(終了)でコードを改善できます。このWhileステートメントは非常に高速に実行されます。あなたはできる:

  • CPU処理を減らすために1秒スリープすることができます。
  • アプリケーションがロックされていないことを確認するために、しばらくの間タイムアウトを設定できます。
于 2012-10-09T13:46:53.617 に答える