【问题标题】:Multithreading in C# with Win.Forms controlC# 中的多线程与 Win.Forms 控件
【发布时间】:2013-03-22 19:38:33
【问题描述】:

我是 C# 的初学者。当我使用 win.forms 时,我遇到了线程问题。我的应用程序冻结。这段代码有什么问题?我正在使用来自msdn 的微软示例。 这是我的代码:

    delegate void SetTextCallback(object text);

    private void WriteString(object text)
    {
        // InvokeRequired required compares the thread ID of the 
        // calling thread to the thread ID of the creating thread. 
        // If these threads are different, it returns true. 
        if (this.textBox1.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(WriteString);
            this.Invoke(d, new object[] { text });
        }
        else
        {
            for (int i = 0; i <= 1000; i++)
            {
                this.textBox1.Text = text.ToString();
            }
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {

        Thread th_1 = new Thread(WriteString);
        Thread th_2 = new Thread(WriteString);
        Thread th_3 = new Thread(WriteString);
        Thread th_4 = new Thread(WriteString);

        th_1.Priority = ThreadPriority.Highest; // самый высокий
        th_2.Priority = ThreadPriority.BelowNormal; // выше среднего
        th_3.Priority = ThreadPriority.Normal; // средний
        th_4.Priority = ThreadPriority.Lowest; // низкий

        th_1.Start("1");
        th_2.Start("2");
        th_3.Start("3");
        th_4.Start("4");

        th_1.Join();
        th_2.Join();
        th_3.Join();
        th_4.Join();
    }

【问题讨论】:

  • 没有例外,我的表单只是冻结了
  • 您是否尝试过调试您的应用程序以查看它究竟是在哪里挂起的?
  • 嗯,很高兴知道!到底什么时候结冰?

标签: c# multithreading winforms


【解决方案1】:

有一个死锁 - UI 线程正在等待线程以 Thread.Join() 完成,而工作线程正在尝试使用阻塞 Control.Invoke() 向 UI 发送消息。用 BeginInvoke() 替换线程代码中的 Invoke 将使死锁消失

 if (this.textBox1.InvokeRequired)
    {
        SetTextCallback d = new SetTextCallback(WriteString);
        // BeginInvoke posts message to UI thread asyncronously
        this.BeginInvoke(d, new object[] { text }); 
    }
    else
    {
        this.textBox1.Text = text.ToString();
    }

【讨论】:

  • 它正在工作,但不是我预期的那样,当我添加 System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false 时它工作正常;在 MyApp_Load 中。但我读到不建议这样做。
  • 尝试添加 System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false 并在 WriteString 中删除所有并添加 textBox1.Text = text.ToString();这是我所期望的结果,但我读到不建议设置 CheckForIllegalCrossThreadCalls = false
  • 对不起,我在设置文本框时更新了我的问题并添加了操作员
  • 当我设置 System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false 和当我像你告诉我的那样写时结果不同
【解决方案2】:

由于加入调用而冻结。 Thread.Join() 让当前线程在另一个线程完成后等待。

【讨论】:

  • 为什么我添加 System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;在 MyApp_Load 中?
  • @goodspeed - 当你禁用检查时,你消除了死锁,因为 InvokeRequired 一直返回 false。
  • 正是 alexm 所说的。您可以删除所有 .Join() 调用,因为您的代码中没有逻辑需要等待所有线程执行其他操作。
  • 我试图理解为什么当我添加 System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false 时一切正常
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-24
  • 2019-09-04
  • 1970-01-01
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多