私のアプリケーションには、進行状況バーとファイル名で構成されるキュー ダウンロード リストがあります。ユーザーがボタンをクリックすると、ファイル名と進行状況バーがインスタンス化され、キューに追加されます。ファイルは一度に 1 つずつ非同期でダウンロードされます。私がやりたいのは、ダウンロードを待機しているファイルのすべての進行状況バーを黄色で保持し、ダウンロード中は緑色に変わり、完了すると青色に変わることです。CheckForIllegalCrossThreadCalls = false;
カスタムプログレスバーのコンストラクターにある場合、現在は機能します。プログレスバーにスレッドセーフな変更を加える方法があるかどうかを確認したいと思います。
各キュー アイテムをオブジェクトとして設定しました。ボタンが押されると、メイン フォーム コード (Form1.cs) からキュー アイテム オブジェクトが作成され、進行状況バーがキュー アイテム コンストラクターで作成されます。これがおそらく問題の始まりです。ダウンロードは、キュー アイテム オブジェクトの関数によって開始されます。
キュー アイテムのスニペット
public class QueueItem
{
public bool inProgress;
public QueueBar bar;
public QueueItem(args)
{
bar = new QueueBar();
inProgress = false;
// handle arguments
}
public void Download()
{
// process info
WebClient client = new WebClient();
client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
client.DownloadFileAsync(url, @savePath);
}
private long lastByte = 0;
private long newByte = 0;
private void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
percentValue = e.ProgressPercentage;
bar.Value = e.ProgressPercentage;
newByte = e.BytesReceived;
}
private void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
// change bar color
bar.Value = 100;
}
}
キュー バーのスニペット
public class QueueBar : ProgressBar
{
// variables
public QueueBar()
{
this.SetStyle(ControlStyles.UserPaint, true);
// initialize variables
}
// function to change text properties
// function to change color
protected override void OnPaint(PaintEventArgs e)
{
// painting
}
}
主な機能の抜粋
public partial class Form1 : Form
{
private List<QueueItem> qItems;
private BackgroundWorker queue;
private void button_Click(object sender, EventArgs e)
{
// basic gist of it
qItems.Add(new QueueItem(args));
Label tmpLabel = new Label();
tmpLabel.Text = filename;
tmpLabel.Dock = DockStyle.Bottm;
splitContainerQueue.Panel2.Controls.Add(tmpLabel);
splitContainerQueue.Panel2.Controls.Add(qItems[qItems.Count - 1].bar);
if (!queue.IsBusy) { queue.RunWorkerAsync(); }
}
private void queue_DoWork(object sender, DoWorkEventArgs e)
{
while (qItems.Count > 0)
{
if (!qItems[0].inProgress && qItems[0].percentValue == 0)
{
qItems[0].inProgress = true;
qItems[0].Download();
}
// else if statements
}
}
また、バックグラウンド ワーカーを作成してキュー アイテムを作成し、コントロールを非同期に追加しようとしましたが、分割コンテナーが別のスレッドで作成されたため、機能しません。