‫欢迎回来｡
‫在本视频中, 我们将了解任务, 特别是使用DWP时的任务｡
‫因此, 让我们创建一个新的项目, 让我们在这里使用WP F, 我将称之为WP F任务和EE在我的情况下｡
‫然后按OC键创建该项目, 现在在UI中添加一个按钮, 我将通过工具箱来完成此操作｡
‫我将选择一个按钮并将其拖动到UI中｡
‫我们就这样了｡
‫我把它放大一点, 把字体改成32, 或者类似的｡
‫现在它更容易阅读了, 我将给予它起个名字｡
‫Name等于我的按钮, 因为我想在后面的代码中使用它｡
‫好吧, 我会的
‫这就是UI｡
‫现在, 我们将在稍后添加一个小Web浏览器, 但现在, 按钮将是好的｡
‫在我的主窗口中, 我想使用那个按钮, 但是我需要一个单击事件｡
‫因此, 每当有人点击该按钮时,
‫我都希望从web上下载一些内容, 一旦下载完成, 我就希望将HTML分配给按钮文本或按钮内容, 因此我需要一个点击事件｡
‫我双击按钮, 它将在此处创建一个新的my button click事件｡
‫所以只要我们点击按钮, 这个方法就会被触发｡
‫最简单的方法就是使用一个消息框, 说“嗨”或者“它工作了”之类的话｡
‫现在, 让我们运行它, 看看我们的代码是否真的有效｡
‫因为在我们做其他事情之前, 让我们先看看按钮是否工作, 它是否会说“嗨”｡
‫好吧, 没关系｡
‫现在, 正如您所看到的, 文本本身实际上没有按钮文本那么大｡
‫这可不好｡
‫但这不是这个视频的主题｡
‫对不对？
‫它是关于任务的, 它是关于在后台下载一些东西, 而UI不会被卡住｡
‫好吧, 那我们就想办法把它卡住｡
‫让我们继续, 尝试下载之类的功能｡
‫为了下载一些东西, 我将使用HTTP客户端, 并调用web客户端｡
‫现在, HTTP客户端是一个类, 我们必须添加system.net, ., http｡
‫这就是我们需要的｡
‫这个web客户端是一个新的HTTP客户端, 现在我需要一个字符串, 它是HTML,
‫它是web客户端的. get string async, 哪个字符串应该得到, 它应该得到https｡
‫冒号正斜杠正斜杠谷歌. com｡
‫我想知道结果｡
‫因此, 下载网站, 并给予我的结果, 并将其存储在HTML｡
‫这就是这个东西的作用｡
‫好吧, 我知道了
‫我要看到的是我正在做的事情｡
‫所以我想看看我正在做的线程｡
‫右行是螺纹编号和螺纹点｡
‫为了使用线程, 我们需要｡
‫使用系统线程, 为了使用调试, 我们需要使用系统诊断｡
‫因此, 让我们完成这两件事, 现在我们可以继续并取得目前的执行绪和Managed执行绪ID｡
‫所以我只想知道我当前运行的线程的ID是什么？
‫因此, 当我单击按钮时, 此调试将被打印出来, 并将下载一些内容｡
‫现在, 假设我想更改按钮内容, 使按钮内容变为done｡
‫让我们来测试一下｡
‫我们到了｡
‫我单击按钮后, 您可以看到现在已完成, 下载完毕｡
‫这是因为这里这个
‫所以下载谷歌｡ com实际上运行得相当快, 这就是为什么它甚至可以做到内容等同于完成｡
‫但通常这是不可能的, 或者在大多数情况下是不可能的, 因为这里的任务通常需要相当长的时间｡
‫我们这里有一个线程, 它非常非常繁重, 因为下载内容通常需要一段时间, 而且在本例中,
‫我们实际下载的内容非常非常少, 我们只是下载了一个非常非常短的Google.
‫com网站｡
‫只有几千字节而已｡
‫所以我不会下载一个5兆字节的文件｡
‫所以这一切都完成之前还需要一点时间｡
‫让我们再检查一遍｡
‫我要按下按钮, 现在你可以看到它冻结了｡
‫只有当它完成了, 它才变成了完成｡
‫因此, 可能是25兆字节的文件太小｡
‫让我们创建一个200 MB的文件｡
‫让我实际上检查是否有一个在网站上, 并有一个｡
‫好吧, 我们再试一次｡
‫现在, 文件将大得多, 将需要相当长的时间来完成｡
‫我按下按钮, 如你所见, 它冻结了, 它冻结了, 它没有任何东西,
‫直到下载完成｡
‫那是因为我们正在进行第三个项目｡
‫因此, 整个屏幕将被冻结, 直到下载完成, 这是非常危险的｡
‫你不应该那样做｡
‫当在主线程或UI线程上执行繁重的任务时, 您应该始终小心,
‫因为主线程或UI线程确实忙碌更新UI｡
‫所以它做了所有的用户界面的东西, 现在我的文件或程序被冻结了｡
‫差不多吧｡
‫所以我将使用一个200 MB的文件｡
‫也许这是一个更好的选择, 这将是这样做, 我们仍然会看到的差异｡
‫好吧, 我知道了
‫所以我只是在这里使用了一个链接, 你可以简单地运行或下载随机文件｡
‫我们再按一次｡
‫正如你现在看到的, 它是冻结的, 它需要一点时间, 直到它完成｡
‫你就在这儿
‫已经结束了
‫所以下载了文件, 就完成了｡
‫好吧, 我会的
‫您还可以看到, 我们正在第一个线程上运行｡
‫这就是主线, 对吧？
‫我们正在主线程上运行, 我们正在尝试下载一些东西, 我们正在尝试更新UI,
‫这就是为什么在这里需要一点时间｡
‫所以现在你可能会说, 好吧, 让我们创建一个任务来完成这个任务｡
‫因此, 让我们创建一个运行的任务, 并在此处运行一些代码｡
‫我就像这样把代码复制到这里｡
‫现在我们来调试一下｡
‫所以, 让我们在这里添加一个调试点｡
‫因此, 让我们继续进行调试, 看看实际涉及哪些线程｡
‫我按下这个按钮, 我们就进入了这个线程｡
‫就这样
‫因此, 我们有几个工作线程｡
‫我们有主线程, 也就是线程1, 我们在前面执行的时候看到过｡
‫因此, 我们有主线程, 然后我们有一个线程, 以及我们的任务运行, 我们在线程五｡
‫因此, 您可以看到线程5是一个工作线程, 这就是我们这里的线程｡
‫那么, 让我们进入下一步｡
‫我们还在, 呃, 执行阶段, 或者说还在第五个线程｡
‫那我们再来一次｡
‫还是五号线｡
‫现在我们要做点什么｡
‫所以我们要更新我的按钮｡
‫好了, 好了
‫让我们再次进入下一步｡
‫如您所见, 我的应用程序冻结｡
‫它是求值表达式, 我的按钮｡
‫所以我们又在等了｡
‫所以相当为之高兴｡
‫如你所见, 女士, 我们正在进行异常行动｡
‫调用线程无法访问该对象, 因为其他线程拥有该对象｡
‫那是什么意思？
‫这意味着我的按钮属于另一个线程｡
‫而通过哪条线｡
‫它由UI线程拥有, 这是我们的主线程｡
‫因此, 主线程负责处理所有UI元素, 以使它们不会冻结｡
‫UI始终响应是很重要的, 在本例中, 它不再响应,
‫因为我们正在尝试访问此行代码, 即使它不在正确的线程中｡
‫现在我们在线程5中, 我们尝试访问属于线程1的内容, 但该内容无效｡
‫因此, 我们在这里得到了这个无效操作异常, 我们需要找到一个不同的解决方案来管理它｡
‫它通常是一个不同线程的概念｡
‫因此, 当您使用不同的线程和对象时, 通常必须非常小心｡
‫如果对象由其他线程拥有, 则不能更改或修改它们｡
‫所以这是你必须要注意的｡
‫那么我们如何才能做到呢？
‫一般来说, 我们先停止应用程序, 然后进入按钮｡
‫因此, 我在这里创建了一个按钮, 并希望签出该按钮｡
‫所以我按下控制键或者按住控制键然后按下按钮｡
‫因此, 按钮继承自button base, button base是一个内容控件,
‫它继承自control､ framework元素和UI元素｡
‫这是一个可视对象, 这是一个依赖对象, 这是一个调度程序对象, 我们是, 所以它是一个调度程序对象｡
‫在这里, 它只检查访问权限并验证X轴｡
‫这是一个调度程序对象, 我们在这里使用了一个调度程序, 调度程序有很多变量, 事件等等.
‫我为什么要给你看这个？
‫这是因为我们将使用dispatcher来管理my按钮的线程｡
‫那么我在这里该怎么办｡
‫好吧, 我需要我的按钮点调度程序, 这样就得到了与系统windows点线程点调度程序对象相关联的windows线程调度程序｡
‫所以现在我们找出哪个线程属于我们的按钮, 或者实际上我们的按钮属于哪个线程｡
‫因此, 让我们检查调度程序, 在这里,
‫我调用在与系统Windows线程调度程序关联的线程上异步执行指定的操作｡
‫这就是我说的我们要做的｡
‫现在我们继续执行该操作, 并在此处执行代码｡
‫所以我要在底部关闭它｡
‫现在, 您可以看到, 我可以继续说, 好的,
‫我的按钮内容显示“已完成”, 我将再次使用调试, 以查看此时我处于哪个线程中｡
‫让我们再次运行代码｡
‫现在让我们按下按钮｡
‫如你所见, 我们现在在这里｡
‫现在, 它需要再次评估负载, 以便我们进入线程5｡
‫现在, 我们在这里进行调试｡
‫然后我们转到下一个线程或下一行｡
‫下一行, 然后UI回到正轨｡
‫在哪里？
‫在这里｡
‫现在我们可以进行下一步了｡
‫我们在调度程序中, 它实际上跳过了我想给你们看的内容｡
‫让我们来看看｡
‫转到Windows, 让我们看看调试控制台, 它是输出, 因此它显示线程号5,
‫然后显示线程号1｡
‫这是第一个线程, 这是第五个线程｡
‫因此, 如您所见, 按钮的所有者是线程1｡
‫为了让它更清楚一点, 我们可以把它加到这里｡
‫Thread number 1或thread number, 某某拥有我的按钮, 现在我们会更清楚一点｡
‫让我们再次运行它, 然后它应该会正确显示｡
‫这是输出结果, 还没有什么有趣的东西｡
‫我们按下按钮, 您会看到执行了第五个线程, 然后开始下载｡
‫一旦它完成了, 一旦它完成了, 它就说这里, 一号线程拥有我的按钮.
‫我们再按一次｡
‫现在, 如您所见, 按钮仍然有效, 并且仍在更新｡
‫这很好｡
‫这是一种方法｡
‫还有另一种方法, 我将向你们展示另一种方法, 这是一种首选的解决方案｡
‫我要复制这个, 我的按钮点击｡
‫我将称之为我的按钮点击, 这样就不会干扰｡
‫现在我要说我在哪一条线上｡
‫那么这里是哪根线呢？
‫我想按一下按钮｡
‫那我应该穿红色的.
‫我将使用一个等待任务运行, 该任务应该是异步任务｡
‫所以我们需要在这里添加async关键字｡
‫现在Visual Studio仍然不是很满意, 所以我需要让这个方法异步｡
‫因此, 这个my button click现在将是一个异步按钮方法, 它将等待一个特定的任务异步运行｡
‫我在这里所做的就是再次下载这个文件,
‫而不是使用调度程序, 我现在可以做的是, 我可以在这个任务之外更新我的按钮｡
‫所以我要在外面做｡
‫我将显示我的按钮内容, 它将显示类似Done downloading的内容｡
‫就这样了｡
‫现在, 我不再使用调度程序（这是一个小的变通办法）, 而是将其设置为异步, 因此现在它应该也能正常工作｡
‫现在, 为了测试它, 我将把这里的方法改成click方法, 变成button click to｡
‫否则, 将永远不会执行此方法｡
‫那就这么办吧｡
‫也许我们还可以加上我们是哪个线程｡
‫所以线程号某某在等待任务之前｡
‫然后这个是在等待任务之后, 那个是在称重任务期间｡
‫现在让我们再运行一次｡
‫我们按下按钮吧｡
‫这里是任务之前
‫这是第一个｡
‫然后在第二个线程的称重任务中｡
‫完成重量任务后, 它又回到了第一位, 我们完成了下载｡
‫所以这是一种不同的方法｡
‫这也很好用, 而且是更好的方法｡
‫所以你不必去检查我在哪个线程的方式？
‫但你创建了一个不同的线程, 你做这些事情, 但你也使它成为一个重量｡
‫所以你让它异步｡
‫现在, 我还想向大家展示一个web浏览器｡
‫我现在要做的就是缩小按钮的大小｡
‫我将把它放在左上角, 我将使用web浏览器｡
‫我要把它拖进去, 让它大一点｡
‫现在我们有了这个网页浏览器, 它应该会显示我们所在的那一面｡
‫因此, 每当我按下按钮时, 我都会下载一个我将手动定义的特定网站｡
‫这只是一个小例子, 补充一下我们目前所看到的｡
‫我不打算进入一个完整的网络浏览器｡
‫我不会教你怎么做｡
‫你可以自己去试试｡
‫我将向您展示如何使用从这个特定链接下载的HTML, 它是硬编码的｡
‫然后简单地使用它或在web浏览器中显示它｡
‫所以https谷歌｡ com的网站｡
‫所以, 只要我按下按钮, 谷歌就会出现｡ 将下载. com｡
‫为了做到这一点, 我需要有一个特定的方法, 我不会手动输入它, 我只会复制并粘贴到这里｡
‫因此, 每当更改依赖项属性时, 都会调用HTML更改上的此方法｡
‫我在这里要说的是, 在HTML中, change需要一个依赖对象和一个依赖属性change, 来调用事件参数,
‫叫做E｡
‫我在这里创建了一个web浏览器, 它将接受该依赖对象, 并将其用作web浏览器｡
‫然后, 如果web浏览器不为空, 则导航到特定字符串, 该字符串将作为字符串的新值｡
‫所以不管这些依赖项参数是什么, 属性更改事件参数是什么, 我就是从那里得到字符串的｡
‫所以这就是需要在web浏览器上显示的内容｡
‫所以我会用一种更简单的方式来做, 但问题是做起来并不那么容易｡
‫所以没有更简单的方法或很多更简单的方法来做到这一点｡
‫这就是你在这里通常需要做的｡
‫因此, 而不是只更新按钮与完成下载, 我想更新网页浏览器, 因此网页浏览器需要一个名称｡
‫我将为web浏览器命名, 并将其命名为我得web浏览器.
‫现在, 我将在这里调用web浏览器, 或者实际上在这里修改它｡
‫我想做的是设置浏览器的值, 然后用一些东西来设置它｡
‫因为你可以看到我们需要依赖属性和一个对象, 它是一个值｡
‫那我该怎么做呢？
‫我从哪里得到的？
‫嗯, 这里有很多很多东西｡
‫其中之一就是我们需要一个依赖属性, 所以让我们创建一个｡
‫我们把它放在最上面｡
‫再一次, 我只需要复制并粘贴它｡
‫我将向您展示它的外观和功能｡
‫所以它是一个只读依赖属性, 称为HTML属性｡
‫我们登记它｡
‫我们用HTML注册它｡
‫如您所见, 它需要一个名称､ 字符串名称､ HTML, 然后是属性类型､ 所有者类型和属性元数据｡
‫这就是我们在WPF一章中使用依赖项属性时所涉及的内容｡
‫这里我用HTML创建了, 类型是字符串.
‫什么是业主？
‫这是主窗口｡
‫我们的类, 这是什么类型的数据, 或者我应该给予它什么数据？
‫我给予它HTML上的更改元数据｡
‫那是什么意思呢？
‫好, 每当我们在HTML上设置HTML属性时, 就会调用changed｡
‫这就是我们要调用的方法｡
‫所以现在我们可以做的就是用下面的代码设置我的浏览器的值｡
‫我们可以继续说HTML属性并使用HTML设置它｡
‫为了使用HTML, 我们需要在这里做一些工作或有一个小的变通办法｡
‫实际上, 我将把它命名为我的HTML, 我需要在这里创建一个变量｡
‫就是一个字符串, 我的http, l, 就是一个写着废话的字符串, 这里有一些愚蠢的文字, 没什么特别的｡
‫但是一旦下载完成, 我们就把结果放到HTML字符串中｡
‫我不能在这里说HTML, 因为这个字符串是在本地创建的, 我不能创建它,
‫或者它在我们的任务范围内, 我不能在外部创建它｡
‫所以我才需要这个小解决方案｡
‫现在我可以说我的HTML是HTML｡
‫所以这个｡
‫变量, 它在我们在这里设置的我的web浏览器的范围内｡
‫这就是为什么我现在可以把它放在这里｡
‫所以在我们待价而沽的任务范围内｡
‫现在, 当然, 我们需要完成这条线｡
‫这就是你设置网页浏览器价值的方法｡
‫好吧, 我会的
‫这是一个小的变通办法, 但它的工作, 所以让我们测试它｡
‫让我们执行代码｡
‫那就按下按钮｡
‫就这样
‫所以我们有很多脚本错误, 但那是因为我们还没有说其他的东西｡
‫但正如你所看到的, 我们现在在谷歌, 所以我们可以去图片, 谷歌地图等｡
‫所以现在我们已经创建了我们的小浏览器, 它只是把我们带到谷歌｡
‫好吧, 酷｡
‫所以正如我所说, 我不打算深入到浏览器和其他东西, 我甚至不想深入到这些主题｡
‫但这只是你必须设置它的方式｡
‫这是一个小, 呃, 是的, 一个小设置, 你需要做的｡
‫所以你需要有这个方法, 你需要有这个依赖属性, 然后你可以继续用HTML属性和一些HTML代码设置浏览器的值, HTML属性是我们的依赖属性,
‫HTML代码是我们从Google下载的HTML代码｡
‫好吧, 我会的
‫再次快速总结一下, 使用不同线程的想法是什么？
‫主线程负责处理UI, 如果要执行一些繁重的任务,
‫则需要一点时间, 例如, 从web下载､
‫从一个文件复制到另一个文件或使用硬盘等｡
‫这就是在后台执行此操作的真正意义所在｡
‫因此, 您可以创建一个不同的任务或线程来处理这些问题｡
‫因此, 我们在这里创建了一个异步任务, 它在后台执行该操作, 一旦完成,
‫我们就可以继续执行其余的操作｡
‫因此, 它不会冻结我们的主线程, 我们的UI仍将正常工作, 这就是它的全部内容｡
‫好吧, 我会的
‫那么在｡