c# - 有没有办法使这段代码线程安全?

标签 c# multithreading

我正在创建一个带有进度条的 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 FormsHow 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/

相关文章:

java - 一个线程上有多个启动

java - 等待另一个线程中的邮件发送完成

multithreading - 在可能出现异常(exception)情况的将来应用 future

c# - Azure 基于时间的函数在发布后不会触发

c# - 如何指定要在 Visual Studio 中停止哪个程序?

c# - .NET 必须指定有效信息?

c# - 如何使用 C# 从 XML 文件中删除节点

c# - MonoDroid 中 OnConfigurationChanged() 的工作原理

java - 在 Java GUI 中使用线程计数

iphone - NSURLConnection 委托(delegate)和线程 - iPhone