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