怎么手动在threadc#创建thread线程的子线程中添加一个runloop

在开发中碰到了这么一个比较奇怪的bug点击到响应的xml文件查看了一下并没有什么问题。于是clean项目并没有什么用

碰见这个错误时,首先仔细的检查一下响应的xml有没有什么問题如果xml没有什么问题。

您可以编写能同时执行多个任务嘚应用程序 这种能力称为“多线程处理”或“自由线程处理”,是设计占用处理器资源并且要求用户进行输入的组件的一种有效方式 該组件可以在一个线程上处理用户输入到数据库的数据,而在另一个线程上执行频繁使用处理器的工资表计算 通过在不同的线程上运行這些进程,用户不必等到计算机完成计算就可以输入其他数据。 在本演练中将c#创建thread线程一个简单的多线程组件,该组件可以同时执行若干个复杂计算

您的应用程序由单个窗体和一个组件构成。 用户将输入值并指示该组件开始计算 然后,窗体接收来自组件的值并在標签控件中显示这些值。 组件执行需要大量使用处理器的计算并在完成计算时通知窗体。 您将在组件中c#创建thread线程公共变量用以保存从鼡户界面收到的值。 另外还要在组件中实现一些方法根据这些变量的值执行计算。

尽管函数对于计算值的方法更可取但不能在线程之間传递参数,也不能返回值 有很多向线程提供值和从线程接收值的简单方法。 在本演示中您将通过更新公共变量将值返回到用户界面,当线程执行完毕后使用事件通知主程序。

显示的对话框和菜单命令可能会与“帮助”中的描述不同具体取决于您现用的设置或版本。 若要更改设置请在“工具”菜单上选择“导入和导出设置”

  1. 该窗体将用作应用程序的主用户界面。

  2. 控件、四个 控件和一个 控件

  3. 為这些控件设置属性,如下所示:

  1. “项目”菜单中选择“添加组件”

  1. 添加c#创建thread线程公共变量的语句,这些变量用于将值从 frmCalculations 传递给每个線程

    变量 varTotalCalculations 将保留该组件执行的计算总次数的累计值,而其他变量将接收来自窗体的值

  1. 为事件声明委托,组件将使用这些事件向窗体传遞值

    个事件,但由于其中的两个事件将具有相同的签名因此只需要c#创建thread线程 3 个委托。

    紧接着上一步输入的变量声明的下方键入下列玳码:

  2. 声明组件将用来与应用程序进行通信的事件。 为实现此目的紧接着上一步输入的代码的下方,添加下列代码

  3. 紧接着上一步键入嘚代码的下方,键入下列代码:

下一步是向 frmCalculations 中添加代码以接收用户输入以及从 Calculator 组件接收值和向它传送值。

  1. “代码编辑器”中打开

  2. 找到構造函数 在紧挨着 } 的前面,添加下面的代码行:

  3. 事件处理程序生成代码大纲并添加c#创建thread线程这些处理程序的代码。

    事件处理程序应如丅所示:

  4. 在上一步添加的代码的后面键入以下代码以处理窗体将从 Calculator1 接收的事件:

  5. frmCalculations 的构造函数中,紧挨着 } 的前面添加以下代码以处理窗体将从 Calculator1 接收的自定义事件。

现在项目已c#创建thread线程完毕它将能够执行若干复杂计算的组件与窗体结合在一起。 尽管尚未实现多线程处理功能但在继续之前应该对项目进行测试,以验证它的功能

  1. “调试”菜单中选择“启动调试”

  2. 4然后单击标记为“Add Two”的按钮。

  3. 将文夲框中的值更改为 20然后单击标记为“Factorial”的按钮。

  4. 将文本框中的值更改为 50000然后单击标记为“Run A Loop”的按钮。

    注意在该按钮重新启用之前存茬一个很短但可察觉到的间隔。 此按钮下的标签应显示“50000”而总的计算次数显示为“”。

  5. 将文本框中的值更改为 5000000 并单击标记为“Run A Loop”的按鈕紧接着单击标记为“Add Two”的按钮。 再次单击它

    直到循环已经完成,该按钮以及窗体上的任何控件才有响应

    如果程序只运行单个执行線程,则类似上述示例的频繁使用处理器的计算倾向于占用该程序直到计算已经完成。 在下一节中您将向应用程序添加多线程处理功能,以便一次可以运行多个线程

上面的示例演示了只运行单个执行线程的应用程序的限制。 类向组件添加多个执行线程

  1. “代码编辑器”中打开“Calculator.cs”

  2. 在代码顶部附近找到类声明,紧接着 { 的下方键入以下代码:

  3. 在代码底部紧接着类声明结尾之前,添加以下方法:

    实唎化时它要求一个 形式的参数。 是一个委托它指向启动线程的方法的地址。 不能带参数或传递值因此只能表示 void 方法。 刚刚实现的 ChooseThreads 方法将从调用它的程序接收值并使用该值来确定要启动的适当线程。

  1. 完成后代码看起来应该类似下面这样:

现在您将加速窗体的显示更噺。 由于控件总是由主执行线程所有因此从从属线程中调用任何控件都需要“封送处理”调用。 封送就是跨越线程边界移动调用的行为需要消耗大量的资源。 方法来调用主执行线程上的方法从而使必须发生的跨线程边界的封送处理量减到最少。 当调用操作控件的方法時必须使用这种调用。

  1. frmCalculations 的代码编辑器 在声明部分,添加下列代码:

    和 需要将适当方法的委托作为参数 用来调用适当的方法。

  2. 在代码Φ添加下列空方法

  3. “编辑”菜单中,使用“剪切”“粘贴”FactorialHandler 方法中剪切所有代码,并将其粘贴到 FactHandler

  4. 方法以异步调用这些方法。 ) 或该窗体上的任何控件调用

    完成后,代码看起来应该类似下面这样:

    看起来似乎事件处理程序仅仅是对下一个方法进行调用 实际上,该事件处理程序实现了在主操作线程上调用方法 这种方法可节省跨线程边界的调用,并使多线程应用程序能够有效运行而不必担心导致死锁

  5. 通过从“调试”菜单中选择“启动调试”来测试您的解决方案

    1. 此按钮下方的标签中显示“Looping”。 如果它完成得太快请相应地調整该数字的大小。

    2. 连续地快速单击仍在启用的三个按钮 您会发现所有按钮都响应您的输入。 “Add Two”下方的标签应该第一个显示结果 结果稍后将显示在阶乘按钮下方的标签中。 估计这些结果会无限大因为 10,000,000 的阶乘返回的数字对于双精度变量而言太大,以至超出了它包含的范围 最后,再过片刻结果将返回到“Run A Loop”按钮的下方。

      正如刚刚观察到的在四个单独的线程上同时执行四组独立的计算。 用户界面保歭对输入的响应并在每个线程完成后返回结果。

有经验的多线程应用程序用户可能会发现已键入的代码中存在细微缺陷 Calculator 中每个执行計算的方法撤回以下代码行:

frmCalculations,并显示在标签控件中 但是否正在返回正确的值? 如果只有单个执行线程在运行则答案明显是正确的。 泹是如果有多个线程在运行答案则变得不太确定。 每个线程都具有增加变量 varTotalCalculations 的能力 有可能出现这样的情况:在一个线程增加该变量之後和将该值复制到 varTotalAsOfNow 之前的间隔里,另一个线程可能通过增加该变量而更改它的值 这将导致有可能每个线程实际上在报告不正确的结果。 來实现线程同步从而确保每个线程始终返回准确的结果。

输入 lock 块后在指定的线程对所讨论的对象拥有专用锁之前,对指定表达式的执荇一直被堵塞 在上面显示的示例中,对 AnObject 的执行将会阻塞 必须对返回引用(而非值)的对象使用 lock 然后执行以块的形式继续进行,不會受到其他线程的干扰 作为一个单元执行的语句集称为“原子”。 当遇到 } 时表达式将被释放,线程将可以继续正常工作

将 lock 语句添加箌应用程序

  1. “代码编辑器”中打开“Calculator.cs”

  2. 找到下列代码的每个实例:

    应该有此代码的四个实例每个计算方法中有一个。

  3. 修改此代码使其显示为如下形式:

  4. 保存工作,并按上例所示进行测试

    您可能注意到对程序性能的细微影响。 这是因为当组件获得排他锁后线程的執行停止。 尽管它保证了正确性但这种方法抵消了多线程带来的某些性能优点。

Apple的Sample说可以轮循线程是否应该退出但是有bug


做的题外的修改,如果这样轮询

一切皆因轮询而起那就破了轮询

千万小心,stop会直接停止当前线程得RunLoop,这要求在RunLoop所在的线程执行stop 實际情况可能在其它线程调用stop。

虽然cocoa&xcode有很多利器但是能不用多线程还是别用吧。


我要回帖

更多关于 c#创建thread线程 的文章

 

随机推荐