簡體   English   中英

C#線程問題

[英]C# threading issue

為了與線程,委托和后台工作人員一起玩,我將一些小應用程序放在一起,其中的一個遇到了一些麻煩。 我有一個Windows窗體,帶有一個文本框,一個按鈕和一個RTF文本。 當我按下按鈕時,文本框中的文本將用作實例化類的參數,如下所示:

public partial class Form1 : Form
{
    private BackgroundWorker backgroundWorker;

    public Form1()
    {
        InitializeComponent();            
    }

    private void button1_Click(object sender, EventArgs e)
    {   
        backgroundWorker = new BackgroundWorker();
        backgroundWorker.DoWork += new DoWorkEventHandler(worker_DoWork);
        backgroundWorker.RunWorkerAsync();
    }

    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        new Thread((ThreadStart)delegate()
        {
            this.BeginInvoke((ThreadStart)delegate()
            {
                foreach (string line in textBox1.Lines)
                {  
                    Dig digger = new Dig(line, textBox1.Text);
                    digger.DomainChecked += new Dig.DomainCheckedHandler(OnUpdateTicker);

                    string response = digger.GetAllInfo();

                    richTextBox1.AppendText(response);
                    Application.DoEvents();
                }
            });
        }).Start();
    }

    void OnUpdateTicker(string msg)
    {
        new Thread((ThreadStart)delegate()
        {
            this.BeginInvoke((ThreadStart)delegate()
            {
                label4.Text = msg;
                Application.DoEvents();
            });
        }).Start();            
    }
}

調試時遇到“ textBox1.Lines”類型為“ Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException”的異常有關如何解決此問題任何提示?

首先,無需在DoWork內部創建新線程; BackgroundWorker的整體思想是DoWork是在單獨的線程上執行的。 其次,由於DoWork是在單獨的線程上執行的,並且只能在UI線程上修改UI控件,因此您需要正確地調用這些更新。 因此, worker_DoWork的重寫版本可能如下所示:

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    foreach (string line in textBox1.Lines)
    {  
        Dig digger = new Dig(line, textBox1.Text);
        digger.DomainChecked += new Dig.DomainCheckedHandler(OnUpdateTicker);
        string response = digger.GetAllInfo();
        richTextBox1.Invoke((Action) delegate { richTextBox1.AppendText(response); });
    }
}

注意代碼如何不顯式生成任何新線程,以及如何通過Control.Invoke調用完成AppendText方法調用,從而迫使其在UI線程上執行。

主要原因是文本框不屬於后台線程。

您的UI線程擁有所有UI對象,並且在按下按鈕時正在旋轉后台線程。 該后台線程不應訪問任何UI對象。

如果要使用文本框的值,則需要以其他方式將其傳遞到后台線程。

在這里查看說明(和解決方案)。

您只能從主線程本身更新主線程上的控件,除非您使用控件的.Invoke方法明確告訴程序可以這樣做。

From: http://www.albahari.com/threading/part3.aspx

Control.Invoke

在多線程Windows Forms應用程序中,從創建它的線程以外的任何線程調用控件上的方法或屬性都是非法的。 必須使用Control.Invoke或Control.BeginInvoke方法將所有跨線程調用顯式編組到創建控件的線程(通常是主線程)中。 一個人不能依賴自動編組,因為它進行得太晚了–只有在非托管代碼中執行得很好時,此時大量內部.NET代碼可能已經在“錯誤的”線程上運行–這不是線程安全的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM