您的位置  > 互联网

长沙会计培训-UI线程操作控件

薪资计算代码如下:

上面的代码我就不过多解释了,相信大家都能看懂。 单击按钮后,将打开一个新线程来执行计算,并将更新 UI 的方法以委托的形式传递给该类。 让我们执行如下:

正如预期的那样,发生了错误,我们无法在新线程中更新 UI 线程。 我们可以使用通用的方法,每个人都应该习惯它。 改写一下,代码如下:

除了上述方法之外,我们还可以使用xt来解决上述问题。 你可能对这个类比较陌生。 我们看一下它的定义,如下:

其定义: 提供在各种同步模型中传播同步上下文的基本功能。 其实它的含义就是对当前线程上下文的封装,或者说是对当前线程所在环境的封装。 封装好的对象可以传递给其他线程,然后在其他线程中调用其Post或Send方法,实现线程间的消息传播。 我们使用xt修改上面的代码,结果是一样的。 代码如下所示:

上面的代码中,首先通过xt.获取UI线程的同步上下文对象,然后在计算工资的线程中使用这个对象的Post方法。 此时控件是在UI线程上下文中执行的,所以不会报错。

到这里,xt的内容其实就结束了,不过还有一点可以补充。 大家应该知道Task对象有一个()方法,用于配置是否同步上下文。 我们来看看这个方法。 代码如下:

ntext 尝试将延续任务编组回原始上下文。 默认为 true。 这里所说的原始上下文实际上是xt,它是异步(await)之前线程的同步上下文。 我们将其改为异步方法,代码如下:

我们知道,异步方法是在遇到await之前在当前线程中执行的。 当执行await行时,方法就会退出,然后await后面的代码就会被封装成一个委托(可能不准确,但这大概意味着,会生成一个状态机类,这个就不讨论了) 。 执行await时,默认会捕获当前线程上下文,然后执行完Task.Delay(1000)后,上面提到的线程上下文会将剩余的代码发送回(Post/Send)到自己的线程中执行。 大概是这样的,代码如下:

上面的代码不一定准确,我只是想表达这个意思。 如果我们不想让剩余的代码在原来的上下文中执行,我们可以将ntext设置为false,这也是微软推荐的。 否则,可能会出现一些意想不到的情况,例如死锁。 我们来看看调用的地方。 代码如下:

我们配置不捕获上下文,代码运行正常。 让我们再次演示一下经典的死锁问题。 如果您仍然感兴趣,请继续阅读。 我们将上面的代码修改为同步等待并默认捕获上下文。 代码如下所示:

我们定义任务变量并删除(false),以便默认情况下捕获上下文。 下面的task.Wait()将等待任务完成,但我们将在线程上下文中执行Post方法。 这个时候我们就会互相等待,造成僵局。 解决办法:凡是使用异步的地方都加上(false),另一处不要使用Wait方法。 使用来异步到底。

终于完成了。 今天讲的内容还是很简单的。 如果能帮到你一点点,我会很高兴(如果你能关注就更好了),哈哈。

最后PS一下这个demo的界面图,让大家看看我的设计能力~~