2016-07-12 7 views
0

初めてDoWorkイベントでは、すべてのメールをダウンロードしており、ProgressChangedイベントに報告し、listView(lvnf)を更新しています。 2回目にすべてのメールをダウンロードし終えたら、今度はボタンをもう一度クリックします.イベントの各行にブレークポイントを追加しましたが、のlistViewイベントを更新し続けます。スロー。どうすればProgressChangedイベントに入り続けることができ、多くのアイテムでlistViewを更新し続けることができますか? ProgressChangedイベントにブレークポイントを追加しました。これは、常にlistViewを更新して停止しますが、reportprogress行のDoWorkイベントで停止することはありません。私はボタンをクリックして二回目について話している!すべての電子メールを初めてダウンロードした後で2回目に発生します。なぜバックグラウンドワーカーはprogresschangedイベントにレポートの進行状況を保持しますか?

private void btnStart_Click(object sender, EventArgs e) 
{ 
    backgroundWorker1.RunWorkerAsync(); 
} 

Doworkイベント:

private MimeKit.MimeMessage newmsg = null; 
private HashSet<string> downloaded = new HashSet<string>(); 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    try 
    { 
     numberofallmessages = 0; 
     using (var client = new Pop3Client()) 
     { 
      client.Connect(textServer.Text, Convert.ToInt32(textPort.Text), ssl); 
      client.AuthenticationMechanisms.Remove("XOAUTH2"); 
      client.Authenticate(textUser.Text, textPassword.Text); 

      var uids = client.GetMessageUids(); 

      for (int i = 0; i < client.Count; i++) 
      { 
       if (backgroundWorker1.CancellationPending) 
       { 
        e.Cancel = true; 
        return; 
       } 
       if (!downloaded.Contains(uids[i])) 
       { 
        allMessages.Add(client.GetMessage(i)); 
        newmsg = client.GetMessage(i); 
        downloaded.Add(uids[i]); 
        SaveFullMessage(client.GetMessage(i), i); 
        w = new StreamWriter(emailsIDSFile, true); 
        w.WriteLine(uids[i]); 
        w.Close(); 
       } 
       int nProgress = (client.Count - i + 1) * 100/client.Count; 
       backgroundWorker1.ReportProgress(nProgress); 
      } 

      client.Disconnect(true); 
     } 
    } 
    catch (Exception err) 
    { 
     string anyerrors = ""; 
    } 
} 

progresschangedイベント

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    pbt.Value = e.ProgressPercentage; 
    pbt.Text = e.ProgressPercentage.ToString() + "%"; 
    pbt.Invalidate(); 
    if (newmsg != null) 
    { 
     ListViewCostumControl.lvnf.Items.Add(new ListViewItem(new string[] 
    { 
     newmsg.From.ToString(),   
     newmsg.Subject,     
     newmsg.Date.ToString() 

    })); 
    } 
} 

完了イベント私が今やった

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    if (closingForm) 
     this.Close(); 
    label8.Text = numberofallmessages.ToString() + "/" + "0"; 
    downloadedallemailsfirsttime = true; 
    countMsg = 0; 
    FileInfo fi = new FileInfo(emailsIDSFile); 
    if (fi.Length > 0) 
    { 
     downloadedallemailsfirsttime = true; 
     lines = File.ReadAllLines(emailsIDSFile); 
     for (int i = 0; i < lines.Length; i++) 
     { 
      seenUids.Add(lines[i]); 
     } 
    } 
} 

と、これまで動作しているようだがDoWorkでありますe私はレポートの進捗にオブジェクトとしてnewmsgを送信してもnewmsgnullを作るよベント:

private MimeKit.MimeMessage newmsg = null; 
private HashSet<string> downloaded = new HashSet<string>(); 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    try 
    { 
     numberofallmessages = 0; 
     countMsg = 0; 
     using (var client = new Pop3Client()) 
     { 
      client.Connect(textServer.Text, Convert.ToInt32(textPort.Text), ssl); 
      client.AuthenticationMechanisms.Remove("XOAUTH2"); 
      client.Authenticate(textUser.Text, textPassword.Text); 

      var uids = client.GetMessageUids(); 

      for (int i = 0; i < client.Count; i++) 
      { 
       if (backgroundWorker1.CancellationPending) 
       { 
        e.Cancel = true; 
        return; 
       } 
       if (!downloaded.Contains(uids[i])) 
       { 
        allMessages.Add(client.GetMessage(i)); 
        newmsg = client.GetMessage(i); 
        downloaded.Add(uids[i]); 
        SaveFullMessage(client.GetMessage(i), i); 
        w = new StreamWriter(emailsIDSFile, true); 
        w.WriteLine(uids[i]); 
        w.Close(); 
       } 

       int nProgress = (client.Count - i + 1) * 100/client.Count; 
       backgroundWorker1.ReportProgress(nProgress,newmsg); 
       newmsg = null; 
      } 

      client.Disconnect(true); 
     } 
    } 
    catch (Exception err) 
    { 
     string anyerrors = ""; 
    } 
} 

と進歩変更イベントで:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    pbt.Value = e.ProgressPercentage; 
    pbt.Text = e.ProgressPercentage.ToString() + "%"; 
    pbt.Invalidate(); 
    MimeKit.MimeMessage mymsg = e.UserState as MimeKit.MimeMessage; 
    if (mymsg != null) 
    { 
     ListViewCostumControl.lvnf.Items.Add(new ListViewItem(new string[] 
     { 
      mymsg.From.ToString(),   
      mymsg.Subject,     
      mymsg.Date.ToString() 
     })); 
    } 
} 

しかし、まだそれがあっても正しい答えではありませんそれは働いている。

+0

冒頭にスペースを追加すると、読みやすくなります。ワーカースレッドからメインスレッドに "newmsg"を転送する方法は全く間違っています。バックグラウンドワーカーのベストプラクティスに関する私の懸念事項では、ProgressChangedイベントを使用して進行インジケータ(テキストボックスと同様)を更新し、workerCompletedを使用してUI(コントロールまたはデータバインドされたアイテム)を更新する結果を転送する必要があります。あなたのリストビュー、一度だけ。 –

+0

@MarcoGuignardそうです。私はコードを変更し、reportprogressでnewmsgを報告しました:backgroundWorker1.ReportProgress(nProgress、newmsg);この行の後に次の行を追加します。newmsg = null; progresschangedになければ、新しいメッセージにnullがないのでlistViewを更新し続けます。 progresschangedイベントで私は追加しました:MimeKit.MimeMessage mymsg = e.UserState MimeKit.MimeMessage; mymsgがnullかどうかを確認してから、listViewをmymsgで更新します。そして、今まで私が行ったすべてのテストは問題なく動作していることを示しています。 –

+0

ちょっとチューニングする必要があります。これはReportProgess(int、New Object(...))のようになります。メインスレッドがProgressChangedイベントでそれを読み取る前に、オブジェクトが第2のスレッドによって「変更」されないように、オブジェクトの詳細コピーを作成する必要があります。もっと詳細についてはこちらをご覧くださいhttp://stackoverflow.com/questions/7332632/how-to-send-more-arguments-in-c-sharp-backgroundworker-progressed-changed-event –

答えて

0

BackgroundWorkerbackgroundWorker1_ProgressChangedの間で1つのprivate MimeKit.MimeMessage newmsgが共有されています。しかし、backgroundWorker1_DoWorkはループ内でnewmsgを変更し続ける。それが変更されるとnewmsgは古い値が破棄され、backgroundWorker1_ProgressChangedはそれが何であったか決してわかりません。ループの反復ごとにclient.GetMessage(i)の値を保存して、反復ごとに何を返したかを伝える必要があります。

まず、この削除:

backgroundWorker1.ReportProgress(nProgress, client.GetMessage(i)); 

そしてbackgroundWorker1_ProgressChangedにしたい:

var newMsg = (MimeKit.MimeMessage)progressChangedEventArgs.UserState; 
if (newMsg != null) 
{ 
    ListViewCostumControl.lvnf.Items.Add(new ListViewItem(new string[] 
    { 
     newmsg.From.ToString(),   
     newmsg.Subject,     
     newmsg.Date.ToString() 
    })); 
} 

編集:backgroundWorker1_DoWorkコールに続いて

private MimeKit.MimeMessage newmsg = null; 

をあなたはReportProgressを呼び出したい場合はしかし、すでに報告されている場合はclient.GetMessage(i)を除外する、backgroundWorker1_DoWorkを次のように変更してください。

MimeKit.MimeMessage newmsg = null; 
if (!downloaded.Contains(uids[i])) 
{ 
    ... 
    newmsg = client.GetMessage(i); 
} 

backgroundWorker1.ReportProgress(nProgress, newmsg); 
+0

あなたの解決策を試しましたが、今度はうまくいきません。編集前の最初の質問と同じ問題です。バックグラウンドワーカーを始めてすべての電子メールをダウンロードした後、私はバックグラウンドワーカーを開始するためにボタンをもう一度クリックしましたが、今度は再びすべてをダウンロードしていないのに、イベントが進行状況を変更したイベントに変更され、var newMsgがnullでなく、listViewの更新が継続されます。しかし、新しい電子メールはまだあるべきではないので、それはすべきではない。 –

+0

私はworkイベントでブレークポイントを使用しましたが、電子メールをダウンロードしていませんが、レポートの進行状況をclient.GetMessage(i)に保ち、listViewを更新し続けます。理由は分かりません。私がバックグラウンドワーカーを始めて、それがクライアントでループしているからです。それを報告しているのでしょうか?わからない。 –

+0

これは別の問題のように聞こえます。 'if(!downloaded.Contains(uids [i]))'の外側で 'backgroundWorker1.ReportProgress(nProgress)'を呼びたいのですか? uids [i]が既にダウンロードされていても、それは進捗状況を報告します。 'uids [i]'のタイプは何ですか? –

関連する問題