我正在创建一个带有进度条的 Windows 窗体程序,它将处理一个包含多行的文件。当我执行以下代码时,button2_Click 方法中的 progressBar1.Maximum 调用执行得很好,但 PostIncident 方法中的调用导致 System.InvalidOperationException,其中指出:“跨线程操作无效:从与创建它的线程不同的线程。”
到目前为止我尝试过的一些途径: 1) 使 PostIncident 返回一个 bool 或 magic 值,以便我将 progressbar1.Maximum 调用拉到 button2_Click 方法中。 我的问题是我的线程技能不足以解决从线程捕获返回值的问题。
2) 尝试在 PostIncident 方法中的 progressbar1.Maximum 调用周围放置一个锁或信号量,这导致了同样的错误。
目前我的解决方案是简单地从项目中完全删除线程,但我确信可能有一个优雅的解决方案,我只是太缺乏经验而看不到。
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);
}
}
最佳答案
看看 Safe, Simple Multithreading in Windows Forms或 How to: Make Thread-Safe Calls to Windows Forms Controls .
您想在 UI 线程上调用 UI 更新。
分割:
- 将业务逻辑分离到一个类(业务层)中。例如:Bussiness1.cs
- 为 UI 相关代码公开该类的公共(public)委托(delegate)。
- 在 Form.cs(UI 层)中为您的业务类设置委托(delegate)值(在本例中为进度条更新)
- 根据需要,类 (Business1.cs) 只需调用委托(delegate)。 (UI层实现)
- UI线程安全:D
不知道这对您来说是否太高级了,但这确实可以帮助您以最佳实践编写代码。
关于c# - 有没有办法使这段代码线程安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38065443/