后台多线程的界面显示

相关知识:
delegate void HandleInterfaceUpdateDelagate(string text);//委托; 类似c语言的函数指针
HandleInterfaceUpdateDelagate interfaceUpdateHandle; // 声明一函数指针
interfaceUpdateHandle = new HandleInterfaceUpdateDelagate(UpdateTextBox); //实例化委托对象 UpdateTextBox 为执行的函数
Dispatcher.Invoke(interfaceUpdateHandle, new string[] { Encoding.ASCII.GetString(buf) }); // 后面的参数对应 string text 为传入的参数

Invoke:
在多线程编程中,我们经常要在工作线程中去更新界面显示,而在多线程中直接调用界面控件的方法是错误的做法,多个线程对一个变量同时访问是非常危险的
所以在编程中我们可以只用Invoke和BeginInvoke来解决这个问题,使多线程中安全的更新界面显示。
正确的做法是将工作线程中涉及更新界面的代码封装为一个方法,通过 Invoke 或者BeginInvoke去调用,
两者的区别就是一个导致工作线程等待,而另外一个则不会。
在编程中,由于界面的更新是很频繁的,所以应尽可能的吧操作对丢给工作线程,尽量让更新界面的UI线程工作量变少
下面说明BeginInvoke的用法 更新窗体中的TextBox..
思路:在主窗口中定义一个委托,其他线程需要进行界面更新的操作时就调用这个委托 如果要在子线程中创建其他窗体,也应该有UI线程来创建,方法类似

正确的做法是用Invoke\BeginInvoke

using System.Threading;
namespace test
{
public partial class Form1 : Form
{
public delegate void MyInvoke(string str1,string str2);// 声明一个委托
public Form1()
{
InitializeComponent();
}
public void DoWork()
{
MyInvoke mi = new MyInvoke(UpdateForm);//实例化委托
this.BeginInvoke(mi, new Object[] {“我是文本框”,”haha”});//启动委托,主线程去执行操作
}
public void UpdateForm(string param1,string parm2)
{
this.textBox1.Text = param1+parm2;
}
private void button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(new ThreadStart(DoWork));
thread.Start();
}
}
}

C# 里委托使用MethodInvoker 很方便
this.BeginInvoke(new MethodInvoker(delegate
{
//do something…
}
));

而WPF的控件,我们找不到Invoke 和 BeginInvoke这两个方法了。因为WPF的UI线程都交给一个叫做调度器的类了。
WPF 应用程序启动时具有两个线程:一个用于处理呈现,另一个用于管理 UI。 呈现线程实际上隐藏在后台运行,而 UI 线程则接收输入、处理事件、绘制屏幕以及运行应用程序代码。UI 线程在一个名为 Dispatcher 的对象中将工作项进行排队。 Dispatcher 根据优先级选择工作项,并运行每一个工作项直到完成。Dispatcher 类提供两种注册工作项的方法:Invoke 和 BeginInvoke。 这两个方法都会安排执行一个委托。Invoke 是同步调用,即它直到 UI 线程实际执行完该委托时才返回。BeginInvoke 是异步调用,因而将立即返回。
上面的代码在WPF中的实现如下:

       Thread t = new Thread(new ThreadStart( delegate

            {

                tb_test.Dispatcher.Invoke(new Action(delegate

                   { 

                       tb_test.Text = "123"; 

                   }), null);

            }));

            t.Start();

参考上述例子:(Messagedisplay_listbox 为控件的名称)(在子线程中,更新控件值)
Messagedisplay_listbox.Dispatcher.Invoke(new Action(delegate()
{
Messagedisplay_listbox.Items.Add(“llsllssl”);
}

Clipboard.SetText(listbox1.Items[listbox1.SelectedIndex].ToString()); 复制listbox中的内容到剪贴板。

猜你喜欢

转载自blog.csdn.net/tiger15605353603/article/details/81406829