在WinForms中,几乎所有的UI都是特定于线程的。您必须使用[STAThread]
以便公共对话框可以工作,并且您不能(安全地)从创建它的任何线程之外的任何线程访问UI元素。从我所听到的,那是因为这就是Windows的工作原理 - 窗口句柄是特定于线程的。
在WPF中,保留了这些相同的限制,因为最终它仍然建立在相同的Windows API之上,仍然是窗口句柄(尽管主要用于顶级窗口),等等。事实上,WPF甚至制作了东西更多限制,因为您甚至无法跨线程访问位图之类的内容。
现在,WinRT是一种全新的访问Windows的方式 - 一个全新的,干净的平板电脑。我们是否仍然坚持使用相同的旧线程限制(具体来说:只能从创建它的线程中操作UI控件),还是让他们打开它?
答案 0 :(得分:9)
我希望期望它是相同的模型 - 但很多更容易使用,至少从C#和VB,使用新的异步处理,让你写一个同步查看方法,只需在等待长时间运行的任务完成后再使用“等待”。
鉴于强调使异步代码更容易编写,MS会放弃同时要求单线程访问UI的效率,这将是令人惊讶的。
答案 1 :(得分:5)
线程模型完全相同。仍然存在单线程和多线程公寓(STA / MTA)的概念,必须通过调用RoInitialize来初始化它。其行为与名称,参数和错误返回中的CoInitialize非常相似。用户界面线程是单线程的,在this video的36:00确认。
答案 2 :(得分:2)
HTML / CSS UI模型本质上是单线程的(直到最近Web工作者出现,JS才支持线程)。 Xaml也是单线程的(因为开发人员很难 很难将代码写入多线程GUI)。
答案 3 :(得分:2)
底层线程模型确实存在一些关键差异。当您的应用程序启动时,会创建一个ASTA(应用程序STA)来运行您的UI代码,如我在演讲中所示。此ASTA不允许重入 - 您在拨打电话时不会收到不相关的电话。这与STA有很大不同。
您可以创建异步工作项 - 请参阅Windows.System.Threadpool命名空间。这些工作项线程自动初始化为MTA。正如拉里所说,网络工作者是JS等同的概念。
您的UI组件是线程关联的。有关如何在UI线程上执行代码的信息,请参阅Windows.UI.Core.CoreDispatcher class。您可以查看线程示例以获取一些示例代码,以便从异步操作更新UI。
答案 4 :(得分:1)
事情在很重要的方面有所不同。
虽然底层线程模型是相同的,但您的问题通常与逻辑并发如何与UI一起工作有关,而开发人员在Windows 8中看到的将是新的。
正如您提到的大多数对话框之前已被阻止。对于Metro应用程序,许多UI组件不会阻止所有组件。还记得WinRT是异步的吗?它也适用于UI组件。
例如,这个.NET 4代码不一定会杀死你的硬盘,因为在Show上的UI调用块(C#示例):
bool formatHardDrive = true;
if (MessageBox.Show("Format your harddrive?") == NO)
formatHardDrive = false;
if (formatHardDrive == true)
Format();
对于Windows 8 Metro,许多UI组件(如 Windows.UI.Popups.MessageDialog )默认为异步,因此Show调用将立即(逻辑上)落到用户之前的下一行代码中检索输入。
当然,基于await / promise设计模式(Javascript示例),有一个优雅的解决方案:
var md = Windows.UI.Popups.MessageDialog("Hello World!");
md.showAsync().then(function (command) {
console.log("pressed: " + command.label); });
关键是虽然线程模型没有改变,但是当大多数人提到UI和线程时,他们正在考虑逻辑并发以及它如何影响编程模型。
总的来说,我认为异步范式的转变是一件好事。它需要稍微改变一下,但它与其他平台在客户端和服务器端的发展方式一致。