标签:协议 contex -- share ini phoenix studio lock key
原文:WPF 支持的多线程 UI 并不是线程安全的
WPF 支持创建多个 UI 线程,跨窗口的或者窗口内的都是可以的;但是这个过程并不是线程安全的。
你有极低的概率会遇到 WPF 多线程 UI 的线程安全问题,说直接点就是崩溃。本文将讲述其线程安全问题。
此问题现已报告给微软:Creating multi-thread UI has a low probability to crash · Issue #297 · dotnet/wpf
必要条件:
现象:
比如下面是其中一种异常:
Exception thrown: ‘System.NullReferenceException‘ in WindowsBase.dll
Object reference not set to an instance of an object.
System.NullReferenceException: Object reference not set to an instance of an object.
at System.IO.Packaging.PackagePart.CleanUpRequestedStreamsList()
at System.IO.Packaging.PackagePart.GetStream(FileMode mode, FileAccess access)
at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
at Walterlv.Bugs.MultiThreadedUI.SplashWindow.InitializeComponent() in C:\Users\lvyi\Desktop\Walterlv.Bugs.MultiThreadedUI\Walterlv.Bugs.MultiThreadedUI\SplashWindow.xaml:line 1
at Walterlv.Bugs.MultiThreadedUI.SplashWindow..ctor() in C:\Users\lvyi\Desktop\Walterlv.Bugs.MultiThreadedUI\Walterlv.Bugs.MultiThreadedUI\SplashWindow.xaml.cs:line 24
at Walterlv.Bugs.MultiThreadedUI.Program.<>c__DisplayClass1_0.<RunSplashWindow>b__0() in C:\Users\lvyi\Desktop\Walterlv.Bugs.MultiThreadedUI\Walterlv.Bugs.MultiThreadedUI\Program.cs:line 33
下图是 .NET Core 3 版本的 WPF 中在 Visual Studio 2019 抓到的异常:
App
和 MainWindow
不变,我们额外创建一个窗口 SplashWindow
。Program
类,并在项目属性中设置 Program
为启动对象(替代 App
)。其他文件全部保持 Visual Studio 生成的默认代码不变,而 Program.cs 的代码如下:
using System;
using System.Threading;
using System.Windows.Threading;
namespace Walterlv.Bugs.MultiThreadedUI
{
public class Program
{
[STAThread]
private static void Main(string[] args)
{
for (var i = 0; i < 50; i++)
{
RunSplashWindow(i);
}
var app = new App();
app.InitializeComponent();
app.Run();
}
private static void RunSplashWindow(int index)
{
var thread = new Thread(() =>
{
var window = new SplashWindow
{
Title = $"SplashWindow {index.ToString().PadLeft(2, ‘ ‘)}",
};
window.Show();
Dispatcher.Run();
})
{
IsBackground = true,
};
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
}
}
说明:即便在 new SplashWindow
代码之前调用以下方法修改 SynchronizationContext
也依然会发生异常。
SynchronizationContext.SetSynchronizationContext(
new DispatcherSynchronizationContext(
Dispatcher.CurrentDispatcher));
我的博客会首发于 https://walterlv.com/,而 CSDN 和博客园仅从其中摘选发布,而且一旦发布了就不再更新。
如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。
标签:协议 contex -- share ini phoenix studio lock key
原文地址:https://www.cnblogs.com/lonelyxmas/p/12052031.html