Profilo di 俊終わりなき旅FotoBlogElenchi Strumenti Guida

俊 储

Professione
Località

終わりなき旅

My Custom Part

誰も皆 悲しみを抱いてる だけど素敵な明日を願っている もう一回 もう一回 もう一回 もう一回!
誰も皆 問題を抱えている だけど素敵な明日を願っている もう一回 もう一回 もう一回 もう一回!
23 novembre

SetThreadAffinityMask函数

SetThreadAffinityMask函数可以将给定的线程到指定的Processor执行,在处理被分解为多个任务且相当耗时的代码时,可以平分给多个Processor以充分利用硬件资源。而主线程可以挂起等待或轮询的方式等待任务的完成。使用SetThreadAffinityMask还可以避免线程代码执行的迁移。

DWORD_PTR WINAPI SetThreadAffinityMask(
  __in  HANDLE hThread,
  __in  DWORD_PTR dwThreadAffinityMask
);
hThread 线程句柄
dwThreadAffinityMask 处理器索引(在Windows 95/98/ME下固定为1)

#include "stdafx.h"
#include <windows.h>

const DWORD SLEEP_TIME = 100;

void threadCallback(LPVOID parameter);

int _tmain(int argc, _TCHAR* argv[]) {
HANDLE hEvent1 = CreateEvent(NULL, TRUE, FALSE, NULL);
HANDLE hEvent2 = CreateEvent(NULL, TRUE, FALSE, NULL);
DWORD dwThreadId1, dwThreadId2;
HANDLE hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadCallback, hEvent1, CREATE_SUSPENDED, &dwThreadId1);
HANDLE hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadCallback, hEvent2, CREATE_SUSPENDED, &dwThreadId2);
SetThreadAffinityMask(hThread1, 1);
SetThreadAffinityMask(hThread2, 2);
ResumeThread(hThread1);
ResumeThread(hThread2);
WaitForSingleObject(hEvent1, INFINITE);
WaitForSingleObject(hEvent2, INFINITE);
CloseHandle(hThread2);
CloseHandle(hThread1);
CloseHandle(hEvent2);
CloseHandle(hEvent1);
system("pause");
return 0;
}

void threadCallback(LPVOID parameter) {
int n = rand() % 100;
for (int i = 0; i < n; ++i) {
printf("%d\n", i);
Sleep(SLEEP_TIME);
}
SetEvent((HANDLE)parameter);
}
21 novembre

Dispatcher Method CheckAccess is Public?

Silverlight中的Dispatcher提供非UI线程在UI线程上运行代码的支持。通过Reflector可以看到Dispatcher的CheckAccess函数声明为public(CheckAccess函数用于检验当前线程ID是否和主UI线程ID相同,如果相同则直接运行代码,否则将当前委托压入工作队列等待执行)。既然CheckAccess函数声明为public为什么在使用Dispatcher类型实例的时候却没有CheckAccess函数提示呢?我们需要编写一个Invoke扩展函数在相同线程直接Invoke,不同线程则通过Dispatcher的BeginInvoke函数:
public static void Invoke(this Dispatcher dispatcher, Delegate d, params Object[] args) {
    if (dispatcher.CheckAccess())
        d.DynamicInvoke(args);
    else
        dispatcher.BeginInvoke(d, args);
}
Dispatcher虽然没有CheckAccess函数提示,上面的代码仍然可以通过编译并执行。原因请注意CheckAccess函数的Attribute声明:
[EditorBrowsable(EditorBrowsableState.Never), SecuritySafeCritical]
public bool CheckAccess()
{
    return (NativeHost.Current.UIThreadID == Thread.CurrentThread.ManagedThreadId);
}
EditorBrowsable属性设置了EditorBrowsableState.Never告诉Visual Studio intelisense该函数不可见。

About Silverlight Path of the Property Data questions

前几天提到了Silverlight(以3.0为准)的复数Path在设置Data属性时和WPF不相同的行为。现在来仔细分析一下导致异常的3种方式:
1. 在Style中设置Path的Data属性
<Style x:Key="ArrowPathStyle" TargetType="Path">
    <Setter Property="Stroke" Value="Black" />
    <Setter Property="StrokeThickness" Value="1" />
    <Setter Property="Data" Value="M 0,0 8,4 0,8 Z" />
</Style>

<Path x:Name="path1" Style="{StaticResource ArrowPathStyle}" />
<Path x:Name="path2" Style="{StaticResource ArrowPathStyle}" />

抛出XamlParseException AG_E_INVALID_ARGUMENT
不通过GeometryConveter直接使用PathGeometry也是相同的错误:
<Style x:Key="ArrowPathStyle" TargetType="Path">
    <Setter Property="Stroke" Value="Black" />
    <Setter Property="StrokeThickness" Value="1" />
    <Setter Property="Data">
        <Setter.Value>
            <PathGeometry>
                <PathFigure StartPoint="0,0" IsClosed="True" IsFilled="True">
                    <LineSegment Point="8,4" />
                    <LineSegment Point="0,8" />
                </PathFigure>
            </PathGeometry>
        </Setter.Value>
    </Setter>
</Style>

2.将PathGeometry定义为静态资源
<PathGeometry x:Key="ArrowPathGeometry">
    <PathFigure StartPoint="0,0" IsClosed="True" IsFilled="True">
        <LineSegment Point="8,4" />
        <LineSegment Point="0,8" />
    </PathFigure>
</PathGeometry>

<Style x:Key="ArrowPathStyle" TargetType="Path">
    <Setter Property="Stroke" Value="Black" />
    <Setter Property="StrokeThickness" Value="1" />
    <Setter Property="Data" Value="{StaticResource ArrowPathGeometry}" />
</Style>

<Path x:Name="path1" Style="{StaticResource ArrowPathStyle}" />
<Path x:Name="path2" Style="{StaticResource ArrowPathStyle}" />
抛出抛出XamlParseException Attribute {StaticResource ArrowPathGeometry} value is out of range. 
如果将Sytle属性的静态资源和Data属性的静态资源分开设置,结果依然和上面相同:
<Path x:Name="path1" Style="{StaticResource ArrowPathStyle}" Data="{StaticResource ArrowPathGeometry}" />
<Path x:Name="path2" Style="{StaticResource ArrowPathStyle}" Data="{StaticResource ArrowPathGeometry}" />

解决方法只能是将Data的属性逐个设置:
<Path x:Name="path1" Style="{StaticResource ArrowPathStyle}" Data="M 0,0 8,4 0,8 Z" />
<Path x:Name="path2" Style="{StaticResource ArrowPathStyle}" Data="M 0,0 8,4 0,8 Z" />

<Path x:Name="path1" Style="{StaticResource ArrowPathStyle}">
    <Path.Data>
        <PathGeometry>
            <PathFigure StartPoint="0,0" IsClosed="True" IsFilled="True">
                <LineSegment Point="8,4" />
                <LineSegment Point="0,8" />
            </PathFigure>
        </PathGeometry>
    </Path.Data>
</Path>
<Path x:Name="path2" Style="{StaticResource ArrowPathStyle}">
    <Path.Data>
        <PathGeometry>
            <PathFigure StartPoint="0,0" IsClosed="True" IsFilled="True">
                <LineSegment Point="8,4" />
                <LineSegment Point="0,8" />
            </PathFigure>
        </PathGeometry>    
    </Path.Data>
</Path>

3. 以编程方式取得PathGeometry Resource设置复数Path的Data 
PathGeometry arrowPathGeometry = this.Resources["ArrowPathGeometry"] as PathGeometry;
path1.Data = path2.Data = arrowPathGeometry;
抛出ArgumentException Value does not fall within the expected range. 作为静态资源的arrowPathGeometry设置Data属性时却导致值在不在预期的范围内。

由于Silverlight没有WPF中的冻结概念,也就是作为静态资源的PathGeometry实质已经被冻结,不再会跟踪它的依赖属性变化以提升性能。这样的限制使静态资源的PathGeometry不能触发动画。Silverlight始终跟踪依赖属性变化,对于PathGeometry不允许共享同一个静态实例。
19 novembre

Silverlight keep walking?

今天MS提供了Silverlight 4.0 beta下载,又有了许多新功能并且支持了MouseRightButtonDown事件。可我还是希望能将那些基础工作做得更好一些。在Silverlight 3.0中如果对Path的Style设置Data属性会引发InvalidOperationException,解决方法只有将Data直接设置到Path本身(同样的行为在WPF中是被支持的)。出现相同异常的还有定义Geometry为资源。看一段XAML:
<Grid x:Name="LayoutRoot" Background="White">
    <Grid.Resources>
        <Style x:Key="PathStyle" TargetType="Path">
            <Setter Property="Stroke" Value="#FF000000" />
            <Setter Property="Data" Value="M 0,0 8,4 0,8 Z" />
        </Style>
        
        <ControlTemplate x:Key="TabItemTemplate" TargetType="localcontrols:TabItem">
            <Canvas>
                <Path Style="{StaticResource PathStyle}" />
                <Path Style="{StaticResource PathStyle}" />
            </Canvas>
        </ControlTemplate>
    </Grid.Resources>
    <localcontrols:TabItem x:Name="tabItem" Template="{StaticResource TabItemTemplate}" />
</Grid>
为了避免上面的异常,必须一个一个的Path设置Data,也无法通过定义PathGeometry为静态资源来避免这个InvalidOperationException。令人费解的行为。

Silverlight TabItem HeaderTemplate doesn't support DataBinding

Silverligt 3.0的TabItem如果自定义HeaderTemplate,那么数据绑定对这个DataTemplate无效,真是个令人崩溃的问题= =。比如下面一段最简单的HeaderTemplate:
<DataTemplate x:Key="TabItemHeaderTemplate">
    <TextBlock Text="{Binding Name}" />
</DateTemplate>
TabItem的DataContext被赋予拥有Name属性的ViewModel。查看TabItem源代码,在OnApplyTemplate函数时内部调用UpdateHeaderVisuals函数设置指定的Template中相应子元素的Content和ContentTemplate。重写TabItem的Template,对其所需的每个ContentControl设置DataContext的TemplateBinding。调试发现相应的ContentControl的DataContext为绑定的ViewModel,但ContentControl的ContentTemplate依然无法绑定。