初めて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
を送信してもnewmsg
null
を作るよベント:
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()
}));
}
}
しかし、まだそれがあっても正しい答えではありませんそれは働いている。
冒頭にスペースを追加すると、読みやすくなります。ワーカースレッドからメインスレッドに "newmsg"を転送する方法は全く間違っています。バックグラウンドワーカーのベストプラクティスに関する私の懸念事項では、ProgressChangedイベントを使用して進行インジケータ(テキストボックスと同様)を更新し、workerCompletedを使用してUI(コントロールまたはデータバインドされたアイテム)を更新する結果を転送する必要があります。あなたのリストビュー、一度だけ。 –
@MarcoGuignardそうです。私はコードを変更し、reportprogressでnewmsgを報告しました:backgroundWorker1.ReportProgress(nProgress、newmsg);この行の後に次の行を追加します。newmsg = null; progresschangedになければ、新しいメッセージにnullがないのでlistViewを更新し続けます。 progresschangedイベントで私は追加しました:MimeKit.MimeMessage mymsg = e.UserState MimeKit.MimeMessage; mymsgがnullかどうかを確認してから、listViewをmymsgで更新します。そして、今まで私が行ったすべてのテストは問題なく動作していることを示しています。 –
ちょっとチューニングする必要があります。これはReportProgess(int、New Object(...))のようになります。メインスレッドがProgressChangedイベントでそれを読み取る前に、オブジェクトが第2のスレッドによって「変更」されないように、オブジェクトの詳細コピーを作成する必要があります。もっと詳細についてはこちらをご覧くださいhttp://stackoverflow.com/questions/7332632/how-to-send-more-arguments-in-c-sharp-backgroundworker-progressed-changed-event –