当前位置:  开发笔记 > 编程语言 > 正文

从另一个线程写入TextBox?

如何解决《从另一个线程写入TextBox?》经验,为你挑选了4个好方法。

我无法弄清楚如何使C#Windows窗体应用程序从一个线程写入文本框.例如,在Program.cs中,我们有标准的main()来绘制表单:

static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
}

然后我们在Form1.cs中:

public Form1()
{
    InitializeComponent();

    new Thread(SampleFunction).Start();
}

public static void SampleFunction()
{
    while(true)
        WindowsFormsApplication1.Form1.ActiveForm.Text += "hi. ";
}

我完全错了吗?

UPDATE

以下是bendewey提供的工作代码示例:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        new Thread(SampleFunction).Start();
    }

    public void AppendTextBox(string value)
    {
        if (InvokeRequired)
        {
            this.Invoke(new Action(AppendTextBox), new object[] {value});
            return;
        }
        textBox1.Text += value;
    }

    void SampleFunction()
    {
        // Gets executed on a seperate thread and 
        // doesn't block the UI while sleeping
        for(int i = 0; i<5; i++)
        {
            AppendTextBox("hi.  ");
            Thread.Sleep(1000);
        }
    }
}

bendewey.. 63

在您的MainForm上创建一个函数来设置文本框检查InvokeRequired

public void AppendTextBox(string value)
{
    if (InvokeRequired)
    {
        this.Invoke(new Action(AppendTextBox), new object[] {value});
        return;
    }
    ActiveForm.Text += value;
}

虽然在静态方法中你不能只是打电话.

WindowsFormsApplication1.Form1.AppendTextBox("hi. ");

你必须在某个地方对Form1进行静态引用,但这不是真正推荐或必要的,你是否只是让你的SampleFunction不是静态的,那么你可以调用

AppendTextBox("hi. ");

如果需要,它将附加在不同的线程上并使用Invoke调用编组到UI.

完整样本

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        new Thread(SampleFunction).Start();
    }

    public void AppendTextBox(string value)
    {
        if (InvokeRequired)
        {
            this.Invoke(new Action(AppendTextBox), new object[] {value});
            return;
        }
        textBox1.Text += value;
    }

    void SampleFunction()
    {
        // Gets executed on a seperate thread and 
        // doesn't block the UI while sleeping
        for(int i = 0; i<5; i++)
        {
            AppendTextBox("hi.  ");
            Thread.Sleep(1000);
        }
    }
}


小智.. 14

或者你可以这样做

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        new Thread( SampleFunction ).Start();
    }

    void SampleFunction()
    {
        // Gets executed on a seperate thread and 
        // doesn't block the UI while sleeping
        for ( int i = 0; i < 5; i++ )
        {
            this.Invoke( ( MethodInvoker )delegate()
            {
                textBox1.Text += "hi";
            } );
            Thread.Sleep( 1000 );
        }
    }
}


Mike.. 14

我会用BeginInvoke,而不是Invoke尽可能多的,除非你真的需要等待,直到你的控制已经更新(在您的例子并非如此).BeginInvoke在WinForms消息队列中发布委托,并让调用代码立即进行(在您的情况下为for循环SampleFunction).Invoke不仅发布代表,还等待它完成.

所以在AppendTextBox你的例子的方法中,你将替换InvokeBeginInvoke:

public void AppendTextBox(string value)
{
    if (InvokeRequired)
    {
        this.BeginInvoke(new Action(AppendTextBox), new object[] {value});
        return;
    }
    textBox1.Text += value;
}

好吧,如果你想得到更多的幻想,还有一个SynchronizationContext类,它可以让你基本上做同样的Control.Invoke/Control.BeginInvoke,但具有不需要WinForms控件引用的优势.这是一个小教程SynchronizationContext.



1> bendewey..:

在您的MainForm上创建一个函数来设置文本框检查InvokeRequired

public void AppendTextBox(string value)
{
    if (InvokeRequired)
    {
        this.Invoke(new Action(AppendTextBox), new object[] {value});
        return;
    }
    ActiveForm.Text += value;
}

虽然在静态方法中你不能只是打电话.

WindowsFormsApplication1.Form1.AppendTextBox("hi. ");

你必须在某个地方对Form1进行静态引用,但这不是真正推荐或必要的,你是否只是让你的SampleFunction不是静态的,那么你可以调用

AppendTextBox("hi. ");

如果需要,它将附加在不同的线程上并使用Invoke调用编组到UI.

完整样本

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        new Thread(SampleFunction).Start();
    }

    public void AppendTextBox(string value)
    {
        if (InvokeRequired)
        {
            this.Invoke(new Action(AppendTextBox), new object[] {value});
            return;
        }
        textBox1.Text += value;
    }

    void SampleFunction()
    {
        // Gets executed on a seperate thread and 
        // doesn't block the UI while sleeping
        for(int i = 0; i<5; i++)
        {
            AppendTextBox("hi.  ");
            Thread.Sleep(1000);
        }
    }
}



2> 小智..:

或者你可以这样做

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        new Thread( SampleFunction ).Start();
    }

    void SampleFunction()
    {
        // Gets executed on a seperate thread and 
        // doesn't block the UI while sleeping
        for ( int i = 0; i < 5; i++ )
        {
            this.Invoke( ( MethodInvoker )delegate()
            {
                textBox1.Text += "hi";
            } );
            Thread.Sleep( 1000 );
        }
    }
}



3> Mike..:

我会用BeginInvoke,而不是Invoke尽可能多的,除非你真的需要等待,直到你的控制已经更新(在您的例子并非如此).BeginInvoke在WinForms消息队列中发布委托,并让调用代码立即进行(在您的情况下为for循环SampleFunction).Invoke不仅发布代表,还等待它完成.

所以在AppendTextBox你的例子的方法中,你将替换InvokeBeginInvoke:

public void AppendTextBox(string value)
{
    if (InvokeRequired)
    {
        this.BeginInvoke(new Action(AppendTextBox), new object[] {value});
        return;
    }
    textBox1.Text += value;
}

好吧,如果你想得到更多的幻想,还有一个SynchronizationContext类,它可以让你基本上做同样的Control.Invoke/Control.BeginInvoke,但具有不需要WinForms控件引用的优势.这是一个小教程SynchronizationContext.



4> Rinat Abdull..:

您需要从拥有该控件的线程执行操作.

这就是我在不增加太多代码噪音的情况下这样做的方式:

control.Invoke(() => textBox1.Text += "hi");

Invoke重载是Lokad共享库的一个简单扩展:

/// 
/// Invokes the specified  on the thread that owns     
/// the .
/// type of the control to work with
/// The control to execute action against.
/// The action to on the thread of the control.
public static void Invoke(this TControl control, Action action) 
  where TControl : Control
{
  if (!control.InvokeRequired)
  {
    action();
  }
  else
  {
    control.Invoke(action);
  }
}

推荐阅读
ar_wen2402851455
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有