C#中,如何达到当前线程,在其他线程创建的东西吗? [英] C# , how reach something in current thread that created in other thread?

查看:140
本文介绍了C#中,如何达到当前线程,在其他线程创建的东西吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写的C#聊天客户端/服务器应用程序,我有问题的线程。我写了这个简单的代码,显示我的问题。



我用thread_1用于显示形式,但它只是显示它第二次(也许thread_1终止和封闭的形式,但我说的IsAlive的活着!)。 Thread_2力争达到上主线程创建texBox但它表明我:




跨线程操作无效:控制'TextBox2中访问从比它创建的线程以外的
线。




我不知道如何解决的第一个问题,但我解决了与BackgroundWorker的,但我的第二个问题想用线程做。有什么办法

 公共部分Form1类:表格
{
公共Form1中()
{
的InitializeComponent();
}

线T1;
螺纹T2;


私人无效的button1_Click(对象发件人,EventArgs五)
{

T1 =新主题(doThread1);
t1.Name =thread_1;

T2 =新主题(doThread2);
t2.Name =thread_2;

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

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

私人无效doThread1()
{
组成FRM2 =新表();
frm2.Show();
}


私人无效doThread2()
{

{
为(INT J = 10000; J> ; 0; j--)
textBox.Text = j.ToString();
}
赶上(异常前)
{
MessageBox.Show(ex.Message);
}
}


}


解决方案

由于Linkerro提到的,你要拿出你调用线程1为你的UI线程将已经在一个线程,当你开始(所有程序都有他们开始在一个单一的主线程)。你是在正确的轨道上,虽然,你要放在一个单独的线程的长时间运行的任务,因此它不会阻止用户界面。唯一的技巧是,你不能从后台线程直接maniuplate UI对象,必须从拥有它们(这是你所得到的说法错误信息)线程操作。



幸运的是在.NET中做到这一点很简单的方法。在WPF使用UiComponent.Dispatcher.Invoke()和WinForms只使用UiComponent.Invoke()。这使您的后台线程能到那里的UI组件生命去更新它的线程。



调用需要它代表了你想对运行操作的委托UI线程。在我的例子我传递这是使用一个黏巴达表达式初始化的行动,以没有参数,没有返回值。



试试这个

 私人无效doThread2()
{

{
为(INT J = 10000; J> 0 ; j--)
{
textBox.Invoke(新动作(()=>
textBox.Text = j.ToString()));
}
}
赶上(异常前)
{
MessageBox.Show(ex.Message);
}
}






这里是你如何能做到这跟任务一个完整的示例。你会看到当它计数可以自由移动窗口,并没有锁定。然而取出任务和退出循环,你会看到窗口如何冻结,因为环路会再阻塞UI线程。

 公共部分Form1类:表格
{
公共Form1中()
{
的InitializeComponent();
}

私人无效的button1_Click(对象发件人,EventArgs五)
{
Task.Factory.StartNew(()=>
{
的for(int x = 0; X<亿; X ++)
{
label1.Invoke(新动作(()=>
label1.Text = x.ToString() ));
}
});
}
}


I'm writing chat client/server app with c# and I have problem with threading. I wrote this simple code for showing my problem.

I used thread_1 for showing Form but it just show it a second (maybe thread_1 terminated and closed the Form , but i IsAlive said its alive !). Thread_2 try to reach texBox that created on main Thread but it shows me:

"Cross-thread operation not valid: Control 'textBox2' accessed from a thread other than the thread it was created on."

I dont know how solve first problem but I solved second problem with BackgroundWorker but i like to do it with thread. Is there any way?

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);
        }
    }


}

解决方案

As Linkerro mentioned, you want to take out the thread you call Thread 1 as your UI will already be in a thread when you start (all programs have a single main thread they start on). You were on the right track though, you want to put any long-running tasks on a separate thread so it doesn't block the UI. The only trick is you cannot directly maniuplate UI objects from background threads, they must be manipulated from the thread that owns them (which is the error message you are getting is saying).

Luckily there is a very easy way to accomplish this in .NET. In WPF you use UiComponent.Dispatcher.Invoke() and Winforms just use UiComponent.Invoke(). This allows your background thread to step over to the thread where the UI component lives to update it.

Invoke takes a delegate which represents the action you would like to run on the UI thread. In my example I pass in an action which is initialized using a lambada expression, taking no parameters and returning no value.

Try this

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);
    }
}


Here is a full example of how you can do this with Tasks. You will see while it is counting you can freely move the window around and it does not lock up. However take out the Task and leave the loop and you will see how the window freezes since the loop would then block the UI thread.

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()));
            }
        });
    }
}

这篇关于C#中,如何达到当前线程,在其他线程创建的东西吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆