我正在使用Visual Studio 2015和.Net
我遇到了一个有点奇怪的问题。我有一个包含两个项目的C#解决方案。一个是标准WPF应用程序,另一个是WPF用户控件库。 WPF应用程序项目是启动项目。
在每个项目中,我都有一个窗口。在启动项目中,我打开窗口并使用CallContext.LogicalSetData
在逻辑调用上下文中设置一个值。这是在加载时完成的。然后我关闭窗口并打开WPF用户控件库中的窗口。我使用逻辑调用上下文中的值填充一个文本框(使用CallContext.LogicalGetData
),这很好。
我有一个按钮,在单击时触发一个事件,该事件使用逻辑调用上下文中的相同值填充另一个文本框 - 但突然之间该值为null。
我可以简单地通过更改启动窗口来使其工作,而不是在加载时执行“事物”,而是按钮事件。
启动窗口代码:
public partial class MainWindow : Window
{
public MainWindow()
{
this.Loaded += OnLoaded;
InitializeComponent();
}
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
CallContext.LogicalSetData("test", "value set onload");
TestWindow win = new TestWindow();
win.Show();
this.Close();
}
private void button_Click(object sender, RoutedEventArgs e)
{
CallContext.LogicalSetData("test", "value set on button event");
TestWindow win = new TestWindow();
win.Show();
this.Close();
}
}
如上所述,如果我在OnLoaded
方法中注释掉这四行,那么它可以正常工作。
另一个窗口:
public partial class TestWindow : Window
{
public TestWindow()
{
InitializeComponent();
PreLoadedText.Text = CallContext.LogicalGetData("test") as string;
}
private void GetValue_Click(object sender, RoutedEventArgs e)
{
string eventTextText = CallContext.LogicalGetData("test") as string;
EventText.Text = eventTextText ?? "The value is null";
}
}
顺便说一下。我尝试使用AsyncLocal<T>
类 - 但我遇到了同样的问题。
示例解决方案可以在这里找到: Visual studio solution as zip file
注意 - 我没有寻找解决方法(我有一对),我正在寻找发生这种情况的原因。
答案 0 :(得分:3)
这是因为Thread.CurrentThread.ExecutionContext
的实例(包含DataStore
的{{1}})在调用之间发生了变化。如果通过在Visual Studio调试器中使用“生成对象ID”为其指定标记,则可以检查它。
为什么会这样?我完全不知道。我试图调试.net Framework源代码而没有任何运气。
就CallContext
而言:它也使用相同的AsyncLocal<T>
,因此会遇到同样的问题。
如果您使用Thread.CurrentThread.ExecutionContext
,则不会发生这种情况,因为它使用的是ThreadLocal<T>
而[ThreadStatic]
本身并未发生变化。