簡體   English   中英

C#,如何在其他線程中創建的當前線程中獲取某些內容?

[英]C# , how reach something in current thread that created in other thread?

我正在用c#編寫聊天客戶端/服務器應用程序,我遇到了線程問題。 我寫了這個簡單的代碼來展示我的問題。

我使用thread_1顯示Form但它只是顯示它一秒鍾(也許thread_1終止並關閉了Form,但我IsAlive說它還活着!)。 Thread_2嘗試訪問在主線程上創建的texBox,但它向我顯示:

“跨線程操作無效:控制'textBox2'從其創建的線程以外的線程訪問。”

我不知道如何解決第一個問題,但我解決了BackgroundWorker的第二個問題,但我喜歡用線程來做。 有什么辦法嗎?

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    Thread t1;
    Thread t2;


    private void button1_Click(object sender, EventArgs e)
    {

        t1 = new Thread(doThread1);
        t1.Name = "thread_1";

        t2 = new Thread(doThread2);
        t2.Name = "thread_2";

        t1.Start();
        t2.Start();

        MessageBox.Show(t1.IsAlive.ToString());
    }

    private void doThread1()
    {
        Form frm2 = new Form();
        frm2.Show();
    }


    private void doThread2()
    {
        try
        {
            for (int j = 10000; j > 0; j--)
                textBox.Text = j.ToString();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }


}

正如Linkerro所提到的,你想要取出你調用線程1的線程,因為當你啟動時你的UI已經在一個線程中(所有程序都有一個主線程開始)。 雖然您處於正確的軌道上,但您希望將任何長時間運行的任務放在單獨的線程上,這樣它就不會阻止UI。 唯一的訣竅是你不能直接從后台線程設計UI對象,它們必須從擁有它們的線程中操作(這是你得到的錯誤信息)。

幸運的是,在.NET中有一種非常簡單的方法可以實現這一點。 在WPF中,您使用UiComponent.Dispatcher.Invoke()和Winforms只使用UiComponent.Invoke()。 這允許您的后台線程轉到UI組件所在的線程以更新它。

Invoke接受一個委托,該委托代表您希望在UI線程上運行的操作。 在我的例子中,我傳入一個動作,該動作使用lambada表達式初始化,不帶參數並且不返回任何值。

嘗試這個

private void doThread2()
{
    try
    {
        for (int j = 10000; j > 0; j--)
        {
            textBox.Invoke(new Action(() =>
                textBox.Text = j.ToString()));
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

以下是如何使用Tasks執行此操作的完整示例。 你會看到它在計數時你可以自由地移動窗口並且它不會鎖定。 然而取出任務並離開循環,您將看到窗口如何凍結,因為循環將阻止UI線程。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Task.Factory.StartNew(() =>
        {
            for (int x = 0; x < 100000000; x++)
            {
                label1.Invoke(new Action(() =>
                    label1.Text = x.ToString()));
            }
        });
    }
}

請參閱從另一個線程寫入TextBox? ,II blieve這回答了你訪問另一個線程中創建的對象的問題。

第一次鏈接出了問題。

暫無
暫無

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

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