私は、多くの行を持つファイルを処理するプログレスバーでwindowsフォームプログラムを作成しています。次のコードを実行すると、button2_ClickメソッドのprogressBar1.Maximum呼び出しはうまく実行されますが、PostIncidentメソッドの1つでは、次のようなSystem.InvalidOperationExceptionが発生します: "クロススレッド操作が有効でない:Control 'progressBar1'それが作成されたスレッド以外のスレッド "このコードをスレッドセーフにする方法はありますか?
これまで試したことがある道は です。1)PostIncidentは、progressbar1.Maximum呼び出しをbutton2_Clickメソッドにプルするように、ブール値またはマジック値を返します。 私の問題は、スレッディングに関するスキルが、スレッドから返された値をキャプチャする際の問題を回避するのに十分ではないことです。
2)プログレスバーの周りにロックまたはセマフォを入れようとしました。PostIncidentメソッドの最大呼び出しで、同じエラーが発生しました。
現時点では、私のソリューションは単にプロジェクトからのスレッドを完全に削除することですが、私は確かに経験のない優雅な解決策があると確信しています。
public partial class ExperianTriggerPoster : Form
{
private readonly OpenFileDialog _ofd = new OpenFileDialog();
public delegate void BarDelegate();
private string _path;
private void button1_Click(object sender, EventArgs e)
{
if (_ofd.ShowDialog() != DialogResult.OK) return;
textBox1.Text = _ofd.SafeFileName;
_path = _ofd.FileName;
}
private void button2_Click(object sender, EventArgs e)
{
string[] sAllLinesFromFile = File.ReadAllLines(_path);
foreach (string line in sAllLinesFromFile)
{
if (!line.StartsWith("N"))
{
progressBar1.Maximum -= 1;
continue;
}
//some logic here...
ThreadPool.QueueUserWorkItem(x => PostIncident(//some parameters here...));
}
}
private void PostIncident(//some parameters here...)
{
//some logic here...
if (customerNo == "not found") // must find a way to make this call thread-safe
{
Log.Information("Could not find customer# for user#: " + userNo);
progressBar1.Maximum -= 1;
}
Invoke(new BarDelegate(UpdateBar));
}
private void UpdateBar()
{
progressBar1.Value++;
if (progressBar1.Value != progressBar1.Maximum) return;
var postingComplete = MessageBox.Show("The posting is complete!", "Experian Trigger Poster", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
if (postingComplete == DialogResult.OK) Environment.Exit(0);
}
}
うわー私はこれをどうやって逃したのか分かりません。とても簡単。ありがとうございました! –