科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件从桌面移动到设备:多线程和用户界面(2)

从桌面移动到设备:多线程和用户界面(2)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本文帮助开发人员克服他们在使用后台线程与用户界面进行交互时Microsoft .NET Compact Framework的局限性,具体内容包括:多线程和用户界面基础知识和构建更好的类。

作者:Jim Wilson 来源:51CTO.com 2007年9月1日

关键字:

  • 评论
  • 分享微博
  • 分享邮件

亡羊补牢

为了使我们的应用程序重新稳定,我们需要修改代码,这样所有与列表框的交互都会在主应用程序线程上发生。通过使用列表框上的 Invoke 方法,我们可以修改代码。Invoke 方法由 System.Windows.Forms.Control 基类提供,因此由所有的 Windows 窗体控件公开。Control.Invoke 方法在最初创建控件的线程上运行某个委托,允许该委托安全地与控件交互。

注.NET Framework 实现可以运行任何委托,与此不同,Control.Invoke 的 .NET Compact Framework 实现只支持 EventHandler 委托。

class MyForm : Form{ ListBox lbData ; MyForm() { InitializeComponent(); // Create form controls Thread t = new Thread(new ThreadStart(Work1_)); t.Start() ; // Runs Work1_ on a background thread } private Queue qData = new Queue(); // Visible to all member functions on all threads void Work1_(){ // Wrap AddItem in delegate EventHandler eh = new EventHandler(AddItem); StreamReader rdr1 = new StreamReader(@"\My Documents\DataFile.dat"); string line = rdr1.ReadLine(); while(line != null) { lock(qData){ // Synchronize queue acess qData.Enqueue(line); // Store line value in queue } lbData.Invoke(eh); // Transfer control to thread that created lbData line = rdr1.ReadLine(); } } void AddItem(object o, EventArgs e) { string line = null; lock(qData){ // Synchronize queue acess line = (string)qData(); // Get data from queue } lbData.Items.Add(line); // Update list box } }

应用程序又稳定了。通过将修改列表框内容的代码移动到 AddItem 函数中,并将它包装到一个 EventHandler 委托中,我们已经将后台任务从它与 UI 的交互中分离出来。循环的每次传递期间,Work1_ 将从文件读取的数据放置到 qData 队列中并调用 lbData.Invoke 来运行包装 AddItem 函数的 EventHandler 委托。每次调用 lbData.Invoke 会挂起运行后台线程,直到主应用程序线程完成运行 AddItem 方法。AddItem 运行在主应用程序线程上,它从队列中提取值并将其安全地添加到列表框中。

克服局限性

对于简单的线程方案,Control.Invoke 的 .NET Compact Framework 实现很适用,但与 .NET Framework 实现相比却具有明显的局限性。

传递参数

首先,.NET Framework 提供了 Control.Invoke 的一种重载,它接受一个对象数组。用该对象数组将参数传递给执行的委托。

通过使用 .NET Framework 中的 Control.Invoke 重载,我们不再需要使用队列或者任何其他的数据结构在线程之间共享数据。数据可以只是作为委托调用的一部分而传递,明显地简化了在后台与 UI 线程之间的数据传递。

使用Control.Invoke重载生成下面Work1_ 与 AddItem的实现。

void Work1_(){ // Wrap AddItem in delegate EventHandler eh = new EventHandler(AddItem); StreamReader rdr1 = new StreamReader(@"\My Documents\DataFile.dat"); string line = rdr1.ReadLine(); while(line != null) { lbData.Invoke(eh, new object[]{line, EventArgs.Empty}); // Pass to AddItem line = rdr1.ReadLine(); } } // o receives the reference to line, e receives EventArgs.Empty void AddItem(object o, EventArgs e) { string line = (string) o; // Upcast o lbData.Items.Add(line); // Add to list box }

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章