为什么不能在WinRT(Windows Store App)中阻止主线程? [英] Why can I not blocking main thread in WinRT(Windows Store App)?

查看:99
本文介绍了为什么不能在WinRT(Windows Store App)中阻止主线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题不是关于我应该阻止我的主线程"的问题,因为通常来说,阻止主/STA/UI线程(用于消息传递和UI操作)是一个坏主意,但是为什么WinRT C ++/cx不允许任何操作与iOS,Android甚至C#相比,主线程的阻塞(尽管await实际上并未阻塞).

This question is not about "should I block my main thread" as it is generally a bad idea to block a main/STA/UI thread-for messaging and UI operations, but why WinRT C++/cx doesn't allow any blocking of the main thread compared to iOS, Android, and even C#(await doesn't actually block though).

Android或iOS阻塞主线程的方式有根本不同吗?为什么WinRT是唯一不允许任何形式的阻止同步的平台?

Is there a fundamental difference in the way Android or iOS block the main thread? Why is WinRT the only platform that doesn't allow any form of blocking synchronization?

我知道在VS2015中需要等待,但是由于向后兼容,我的公司仍然使用VS2013.

I'm aware of co-await in VS2015, but due to backward compatibility my company still uses VS2013.

推荐答案

大话题,以惊人的速度发展.这延续了很久以前在COM中开始的传统. WinRT继承了所有相同的概念,但确实得到了相当大的清理.基本的设计考虑因素是线程安全性是库设计中最困难的方面之一.而且任何一个库都具有从根本上讲是线程不安全的类,如果该库的使用者不知道它,那么他将很容易地创建一个令人讨厌的bug,难以诊断.

Big topic, at break-neck speed. This continues a tradition that started a long time ago in COM. WinRT inherits about all of the same concepts, it did get cleaned-up considerably. The fundamental design consideration is that thread-safety is one of the most difficult aspects of library design. And that any library has classes that are fundamentally thread-unsafe and if the consumer of the library is not aware of it then he'll easily create a nasty bug that is excessively difficult to diagnose.

对于依赖于封闭源业务模型和1-800支持电话号码的公司而言,这是一个丑陋的问题.这样的电话可能非常令人讨厌,线程错误总是需要告诉程序员您不能这样做,必须重写代码".几乎是可以接受的答案,也不是这样:)

This is an ugly problem for a company that relies on a closed-source business model and a 1-800 support phone number. Such phone calls can be very unpleasant, threading bugs invariably require telling a programmer "you can't do that, you'll have to rewrite your code". Rarely an acceptable answer, not at SO either :)

因此,线程安全性不被视为程序员需要自己正确处理的事后想法. WinRT类显式指定它是否是线程安全的(ThreadingModel属性),以及如果以某种不安全的方式使用它,则应如何使它成为线程安全的(MarshallingBehavior属性).大多是有关运行时的详细信息,请注意编译器警告C4451甚至如何使这些属性产生编译时诊断.

So thread-safety is not treated as an afterthought that the programmer needs to get right by himself. A WinRT class explicitly specifies whether or not it is thread-safe (the ThreadingModel attribute) and, if it is used in an unsafe way anyway, what should happen to make it thread-safe (the MarshallingBehavior attribute). Mostly a runtime detail, do note how compiler warning C4451 can even make these attributes produce a compile-time diagnostic.

反正以不安全的方式使用"子句就是您要问的问题. WinRT可以使一个类本身不是线程安全的,但是有一个一个细节无法自行解决.为了使其安全,它需要知道创建该类的对象的线程是否可以支持操作系统提供的使该对象安全的方式.如果线程不存在,则操作系统必须自己创建一个线程才能为对象提供一个安全的家.解决了问题,但是效率很低,因为必须对每个方法调用进行整理.

The "used in an unsafe way anyway" clause is what you are asking about. WinRT can make a class that is not thread-safe safe by itself but there is one detail that it can't figure out by itself. To make it safe, it needs to know whether the thread that creates an object of the class can support the operating system provided way to make the object safe. And if the thread doesn't then the OS has to create a thread by itself to give the object a safe home. Solves the problem but that is pretty inefficient since every method call has to be marshalled.

您必须做出承诺,跨您的心愿到死的风格.如果您的线程解决了生产者-消费者问题<,操作系统可以避免创建线程/a>.在Windows方面更广为人知的是泵送消息循环".操作系统本身无法弄清某些事情,因为通常在之后创建线程不安全的对象之后才开始运行.

You have to make a promise, cross-your-heart-hope-to-die style. The operating system can avoid creating a thread if your thread solves the producer-consumer problem. Better known as "pumping the message loop" in Windows vernacular. Something the OS can't figure out by itself since you typically don't start to pump until after you created a thread-unsafe object.

您再做出一个承诺,即您也保证使用者不会阻止并停止接受来自消息队列的消息.阻塞是不好的,隐含的是在使用者正在阻塞时工作线程无法继续.更糟的是,阻塞很可能导致死锁.当涉及两个同步对象时,线程问题始终是一个重大风险.您阻止的一个,另一个隐藏在等待呼叫完成的操作系统中.当您看不到导致死锁的同步对象之一的状态时,请诊断死锁.

And just one more promise you make, you also promise that the consumer doesn't block and stops accepting messages from the message queue. Blocking is bad, implicit is that worker threads can't continue while the consumer is blocking. And worse, much worse, blocking is pretty likely to cause deadlock. The threading problem that's always a significant risk when there are two synchronization objects involved. One that you block on, the other that's hidden inside the OS that is waiting for the call to complete. Diagnosing a deadlock when you can't see the state of one of the sync objects that caused the deadlock is generally unpleasant.

强调 promise ,如果您违反诺言并阻止,操作系统将无能为力.它会让您,而且不一定致命.它通常不是,也不会导致无响应的UI.在CLR上运行的托管代码不同,如果阻塞,则CLR将启动.通常可以使用,但是会引起一些令人困惑的重新进入错误.该机制在本机C ++中不存在.死锁实际上并不是很难诊断的,但您必须找到等待STA线程恢复正常运行的线程.它的堆栈跟踪说明了这个故事.

Emphasis on promise, there isn't anything the OS can do if you break the promise and block anyway. It will let you, and it doesn't necessarily have to be fatal. It often isn't and doesn't cause anything more than an unresponsive UI. Different in managed code that runs on the CLR, if it blocks then the CLR will pump. Mostly works, but can cause some pretty bewildering re-entrancy bugs. That mechanism doesn't exist in native C++. Deadlock isn't actually that hard to diagnose, but you do have to find the thread back that's waiting for the STA thread to get back to business. Its stack trace tells the tale.

使用C ++/CX时要小心这些属性.除非明确提供它们,否则您将创建一个始终被认为是线程安全的类(ThreadingModel = Both,MarshallingType = Standard).一个不经常实际测试的方面,将是破坏期望的客户端代码.好了,您会打个电话,并且必须给一个不愉快的答案:)还请注意,OSX和Android并不是仅有的不提供WinRT保证的运行时系统的唯一示例,.NET Framework也没有.

Do beware of these attributes when you use C++/CX. Unless you explicitly provide them, you'll create a class that's always considered thread-safe (ThreadingModel = Both, MarshallingType = Standard). An aspect that is not often actually tested, it will be the client code that ruins that expectation. Well, you'll get a phone call and you have to give an unpleasant answer :) Also note that OSX and Android are hardly the only examples of runtime systems that don't provide the WinRT guarantees, the .NET Framework does not either.

这篇关于为什么不能在WinRT(Windows Store App)中阻止主线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆