在线程间调用中使用匿名方法和匿名委托

在.NET中,辅助线程引发的事件如SerialPort.DataReceived需要通过Invoke来同步或异步调用UI元素。Action和Func委托配合匿名方法可以简化这一过程,减少重复代码。例如,在DataReceived事件中,可以使用匿名委托直接更新TextBox内容,提高代码清晰度和效率。

 

 

.NET中,许多IO设备的事件是在辅助线程上引发,如System.IO.Ports.SerialPortDataRecieved事件。在MSDN中讲道:

SerialPort 对象接收数据时,将在辅助线程上引发 DataReceived 事件。 由于此事件在辅助线程而非主线程上引发,因此尝试修改主线程中的一些元素(如 UI 元素)时会引发线程异常。如果有必要修改主 Form Control 中的元素,请使用 Invoke 回发更改请求,这将在正确的线程上执行。

在实际使用中,若需要同步调用,则使用Control.Invoke方法,异步调用使用Control.BeginInvoke方法(WPF中使用Dispatcher.InvokeDispatcher.BeginInvoke)。这几个方法都由两个重载,声明如下:

名称

说明

Invoke(Delegate)

在拥有此控件的基础窗口句柄的线程上执行指定的委托。

Invoke(Delegate, array< Object []()>[])

在拥有控件的基础窗口句柄的线程上,用指定的参数列表执行指定委托。

例如,在一个串口DataReceived接收事件中,当接收到一个指定字串后,需要在Form上某个TextBox中显示接收到的数据,则可以这样使用:

public delegate void HandleReceivedCallback(string text);

//……

private void HandleReceived(string text)

        {

            this.textBox1.Text = text;

        }

 

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)

        {

            string text = serialPort1.ReadLine();

            this.Invoke(new HandleReceivedCallback (HandleReceived), new object[] { text });

        }

即要跨线程调用,应该包含3个步骤:

1) 声明一个调用委托;

2) 定义一个调用函数(委托实例);

3) 采用Invoke调用该委托。

若存在多处跨线程调用,而每一个被调用函数都比较简单且仅在此处调用,则使用上面的方法会增加较多重复的操作(声明委托、定义函数),此时可以利用匿名委托和匿名函数来简化该步骤。

.NET 3.5以后,System命名空间提供了两类委托泛型:ActionFunc。其中,Action用来代表无返回值委托,Func用来代表有返回值委托。同时,.NET 3.5也提供了匿名方法(lambda表达式实际上也是一种匿名方法)来作为内联编码方式。上面的操作如果采用匿名委托和匿名方法,则可以这样使用:

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)

        {

string text = serialPort1.ReadLine();

            this.Invoke(new Action<string>(delegate(string txt)

            {

                this.textBox1.Text = txt;

            }), new object[] { text });

        }

这段代码与之前的代码作用完全相同,但其减少了声明委托、定义方法的操作。对于有较多只在一处线程间调用的,这种实现方法可以减少相当一部分工作量,并且可以使程序代码更加清晰。

注:在辅助线程上引发的常用对象还有System.Timers.Timer类的Elapsed事件。不过Timer类提供了用于操作用户界面提供了另一种简便的方法:如果和用户界面元素(如窗体或控件)一起使用 Timer,请将包含有 Timer 的窗体或控件赋值给 SynchronizingObject 属性,以便将此事件封送到用户界面线程中。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值