“阻断疗法” - 拯救 WPF 启动过程中发生设备热插拔导致触摸失效问题
如果你在WPF程序启动过程中进行设备热插拔(例如,插入一个U盘,一个USB摄像头),那么你的WPF程序很有可能失去所有触摸消息响应,通过 Tablet.TabletDevices.Count 检查当前程序的挂靠触摸设备,发现为0。有趣的是,如果你将触摸线重新插拔后,程序恢复正常。所以,这是WPF的Bug,微软的锅。那么这个锅的根本原因是啥?有兴趣的可以调试 .net framework 源码,这里没有深究。
如果你在WPF程序启动过程中进行设备热插拔(例如,插入一个U盘,一个USB摄像头),那么你的WPF程序很有可能失去所有触摸消息响应,通过 Tablet.TabletDevices.Count 检查当前程序的挂靠触摸设备,发现为0。有趣的是,如果你将触摸线重新插拔后,程序恢复正常。所以,这是WPF的Bug,微软的锅。那么这个锅的根本原因是啥?有兴趣的可以调试 .net framework 源码,这里没有深究。
Lens: Nikkor 24-mm F2.8
f2.8 70mm ISO400
在上一篇文章D3DImage - 它能做啥、解决了什么问题、有哪些瓶颈、怎么最佳实践最后,提到DropShadowEffect严重影响到D3DImage的渲染性能问题,导致程序在渲染8分屏(8个远端视频)的时候,出现严重的性能下降,渲染卡顿。要知道,在使用原生窗口渲染方案渲染8分屏,CPU占用和内存占用也不过25%和~200Mb,稍差一点,使用D3DImage优化后方案渲染,CPU占用并没有出现多大的跳跃,大约在30%左右。即使是添加了DropShadowEffect的情况下,CPU占用和内存占用好像都没有多大变化;既然在CPU和内存占用都没有多大变化的情况下,WPF渲染卡顿,那肯定(可能吧)是“帧生成”时间过长的锅。
D3dImage,.Net Framework 3.5 之后,微软提供的一个全新的ImageSource对象,可以在WPF中很好的呈现DirectX内容;在此之前,你只能将DirectX内容直接渲染在Windows窗口之上,这必然引起令人头疼的AirSpace问题,为了在这些内容上面添加我们习以为常的WPF UI 元素,你只能使用Popup来承载这些内容,完全丧失WPF UI开发的灵活性,且有经验的WPF程序员都知道一个事实:WPF Popup就是一个深坑 - 你需要手动处理各种显示隐藏问题、因为其导致的焦点问题,显示层级问题以及最令人头疼的性能问题,特别是在4K屏幕下,因为我们都知道,Popup就是一个Window,为了解决Airspace问题而使用Popup来承载UI必定需要使其AllowTransparency=True,这就引起了另外一个问题,透明窗口占用内存与其面积成正相关,在4K屏幕下,你可能将整个程序大部分的内存占用贡献给了这些Popup UI。说了这么多,好像在诉控Popup有多么的垃圾(它的确如此,如果在做大量的UI容器时)。
年轻人,如果你觉得Airspace问题真的没有办法解决了,只能用Popup这种技术手段来规避了,那么听老人一句话,不要浪费时间在Popup上了,因为你在前期投入的时间来规避种种Popup UI导致的问题以及各种你意想不到的Bug,到最后总会碰到解决不了,完全不能规避的情况,从而导致整个Popup UI替换方案完全失败的情形。
废话少说,要解码一个视频帧,你需要这样做:
获得帧数据后,用SDL还是直接用D3d渲染,那就看你自己了。
在.Net Framework 3.5 SP1中,微软在WPF中提供了D3DImage对象,D3DImage是一个ImageSource,这可以让我们在WPF原生的D3D Surface上渲染Direct3D Surface,大大提高了WPF和DirectX内容的交互性。
在此之前,要想在WPF上渲染DirectX的内容,只能让DirectX直接渲染到窗口上,这样会造成不可避免的Airspace问题,因为DirectX内容要时刻刷新重绘,导致WPF窗口上的其他内容被覆盖,表现就是DirectX内容始终在窗口最顶层。
正如前面所说,D3DImage是一个ImageSource,在WPF中,这意味着,我们可以将一个3D场景变成一个Image对象的Source,或者构建一个ImageBrush,这意味这D3D Surface可以渲染到WPF中任意一个以Brush进行渲染的元素上,例如图片,文本前景色,元素背景色等等。
如下,就是一个典型的应用D3DImage的代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14if (d3dimg.IsFrontBufferAvailable)
{
IntPtr pSurface = IntPtr.Zero;
pSurface = _view.GetBackBuffer();
if (pSurface != IntPtr.Zero)
{
d3dimg.Lock();
d3dimg.SetBackBuffer(D3DResourceType.IDirect3DSurface9,pSurface);
_view.Draw();
d3dimg.AddDirtyRect(new Int32Rect(0, 0, d3dimg.PixelWidth, d3dimg.PixelHeight));
d3dimg.Unlock();
}
}
只需要Direct3D内容渲染的Surface接口指针即可,如上面的pSurface。
原文地址: http://blog.stephencleary.com/2013/11/there-is-no-thread.html
最纯粹的async形式中存在一个重要的真相:这里并没有线程(或者不存在新建的线程)
举不胜数的反对者哭喊道:“不!如果我正在等待一个操作,那一定存在一个线程在等待这个操作!它可能是一个线程池中的线程。或者是系统线程!或者是其他类似设备驱动的东西…”。
不要听从那些哭喊的人。如果那些async操作是纯粹的,那么这里将不会存在线程。
曼德博集合(Mandelbrot set,或译为曼德布洛特复数集合)是一种在复平面上组成分形的点的集合,以数学家本华·曼德博的名字命名。曼德博集合与朱利亚集合有些相似的地方,例如使用相同的复二次多项式来进行迭代。(维基百科)
其中的迭代公式: