WPF BUG
- BUG_1:找不到资源bug
- BUG_2:设置属性时,导致栈溢出问题
- BUG_3 :动态资源加载成功,但是无法使用
- BUG_4:另一个线程已经拥有对象
- BUG_5:WPF窗口销毁时其对象被线程的委托调用出错 # WRONG!
- BUG_6:GDI+一般性错误
- BUG_7:EmguCV尝试写入受保护的内存,这通常表示内存损坏
- BUG_8:MVVM下绑定Image出错::“必须在与 DependencyObject 相同的线程上创建 DependencySource。”
- BUG_9:使用Mysql数据库时,出现No data is available for encoding 1252.
- BUG_10:The given key 'utf8mb4' was not present in the dictionary
- BUG_10:当前 .NET SDK 不支持将 .NET Core 3.1 设置为目标。请将 .NET Core 3.0或更低版本设置
BUG_1:找不到资源bug
1.描述
显示在某个DLL中调用资源失败。显示如下:
System.IO.IOException:“找不到资源“test/cameratest/cameratestviewd.xaml”。”
2.解决
1.检查 在App.xaml文件中,SartupUri位置设置是否正确
2.检查 指定文件夹是否存在该资源。
BUG_2:设置属性时,导致栈溢出问题
1.问题描述
栈溢出。
2.解决
此处属性设置不合理导致循环检测IsDisplay,最后栈溢出。
SourcePlayer = value;
//改为
sourcePlayer = value;
便可以解决问题。
总结:
注意属性的设置,这是基本功。
BUG_3 :动态资源加载成功,但是无法使用
1.描述
//这里的代码是正确的。但是Loginbg并没有被使用为MainWindow的动态资源背景。
//App.xaml应该是最先被运行的。生成动态资源,然后运行初始界面。界面使用动态资源。
//因此我在窗口初始化中直接设置图片资源。后面应该改动,在app类中集中添加资源。
private void InitResources()
{
string bg_Path = @"C:\Users\Administrator\source\repos\选课系统\选课系统\Resources\Jpg\" + "loginbg.jpg";
if (System.IO.File.Exists(bg_Path))
{
BitmapImage bgImg = new BitmapImage();
bgImg.BeginInit();
bgImg.UriSource = new Uri(bg_Path, UriKind.Absolute);
bgImg.EndInit();
Current.Resources.Add("Loginbg", bgImg);
}
}
以上代码将图片加入WPF的资源字典中。App类是最先初始化的,因此应该图片是加载成功了的。但是主窗口无法调用动态资源。
<Grid.Background >
<ImageBrush x:Name="grid_bg" ImageSource="{DynamicResource Loginbg}"/>
</Grid.Background>
2.解决
暂无
BUG_4:另一个线程已经拥有对象
1.描述
在多线程下,线程之间不能拥有相同的对象。即线程1不能对线程2的对象进行操作。
//线程1创建窗口控件
Label label1=new Label();
//线程2对控件操作。
label1,Content = “1”;
//以上语句会抛出异常:另一个线程已经拥有对象
2.解决
线程2对线程1发起委托,在委托中进行操作即可。
两种代码格式:
System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
{
//此处进行操作
label1.Content = "1";
}));
或者
// 委托
System.Windows.Application.Current.Dispatcher.Invoke(new Action(
delegate
{
//此处进行操作
label1.Content = "1";
}));
BUG_5:WPF窗口销毁时其对象被线程的委托调用出错 # WRONG!
1.描述
我在窗口注册了一个函数:
Closed="Window_Closed"
其函数如下:
private void Window_Closed(object sender, EventArgs e)
{
空隙
//关闭线程操作
}
当我点击退出窗口的时候,在代码上的空隙之前,窗口就先被销毁了。即先执行窗口销毁,在执行Window_Closed函数。这是主线程(拥有窗口对象的线程)执行的操作。
在空隙的这一段时间,如果其他线程对主线程的对象有操作的话(如上一个BUG),会出现“对象引用为空”。
解决
出现上述问题的原因是,线程是异步的,线程1销毁了窗口对象,但是线程2不知道,在Window_Closed执行前,窗口已经销毁;执行到Window_Closed的关闭线程的操作前,有可能线程2的委托仍在对线程1中已经销毁的对象进行操作,导致错误。
因此,不让线程1在 空隙 前销毁窗口对象即可。使用GC.KeepAlive函数:
private void Window_Closed(object sender, EventArgs e)
{
空隙
//关闭线程操作
GC.KeepAlive(this.OwnedWindows);
}
总结GC.KeepAlive函数
GC.KeepAlive函数源码:
GC.KeepAlive( Object obj)
{
//次函数不进行任何操作
}
作用是引用某个对象,告诉GC这个对象暂时不能销毁。
BUG_6:GDI+一般性错误
1.描述
对图像进行保存时,出现这个错误。
Mat frame = new Mat(imgPath);
using (Bitmap bmp = frame.Bitmap)
{
Image<Bgr, byte> image = new Image<Bgr, byte>(bmp);
image.Save(SavePath+"1.jpg");
image_1.Dispose();
}
具体情况是前面几张图片可以保存成功,运行不就便会出现经典的“GDI+一般性错误”。
即路径是可用的,也保存成功了(有权限),但是仍会出现这个错误。
2.解决
无
BUG_7:EmguCV尝试写入受保护的内存,这通常表示内存损坏
1.描述
当Mat转为Image,在转为IImage格式是会出错。
Mat frame = new Mat();
Image<bgr,byte> image = new Image<bgr,byte>(frame.Bitmap);
//ImageBox是EmguCV的组件,用于播放Mat流
ImageBox.Image = image;
2.解决
暂无。暂时是用WPF的普通image组件代替。
BUG_8:MVVM下绑定Image出错::“必须在与 DependencyObject 相同的线程上创建 DependencySource。”
1.描述
img属性,用于绑定。
BitmapSource img;
public BitmapSource Img
{
get
{
return img;
}
set
{
img = value;
RaisePropertyChanged(() => Img);
}
}
使用EmguCV进行抓帧
Caputure caputure = new Caputure();
capture.ImageGrabbed += Capture_ImageGrabbed;
capture.Start();
这是caputure的抓帧回调
private void Capture_ImageGrabbed(object sender, EventArgs e)
{
try
{
Dispatcher.CurrentDispatcher.Invoke(new Action(() =>
{
using (Mat frame = new Mat())
{
capture.Retrieve(frame, 0);
count++;
Console.WriteLine("测试");
Text = "传输视频图像 " + count.ToString();
BitmapSource bs = BitmapConversion.BitmapToBitmapSource(frame.Bitmap);
//这里是关键
//bs.Freeze();
Img = bs;
}
}));
}
catch (Exception ex)
{
MessageBox.Show($"{ex}");
}
}
注意:以上函数的bs.Freeze()是被注释掉的。没有加此语句时,便会报出“标题”错误。
2.解决
BitmapSource继承自Freezable,不管BitmapSource对象在哪个线程创建,只要没有被冻结,就不能使用这个对象。
BitmapSource bmp = new BitmapSource();
BitmapSource bmp = BitmapConversion.BitmapToBitmapSource(frame.Bitmap);
bmp.Freeze();//表示将bmp冻结,bmp将不能再被修改,可以赋给Image控件。
//冻结之后,不应该再被修改,否则要再次Freeze
Img = bmp;//赋给Image控件
BUG_9:使用Mysql数据库时,出现No data is available for encoding 1252.
1.描述
c#使用数据库连接时:
string connectStr = "Server = localhost; Database = hello; Uid = root; Pwd = admin123; ";
MySqlConnection mySqlConnection = new MySqlConnection(connectStr);
mySqlConnection.Open();
Open语句出现错误:“No data is available for encoding 1252. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method”。
2.解决
1.加入以下语句:
System.Text.EncodingProvider ppp = System.Text.CodePagesEncodingProvider.Instance;
Encoding.RegisterProvider(ppp);
添加以上代码时,又会出现这个错误:“Could not load file or assembly ‘System.Diagnostics.PerformanceCounter, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51’. 系统找不到指定的文件。”
2.在Nuget添加
System.Diagnostics.PerformanceCounter程序包即可。
BUG_10:The given key ‘utf8mb4’ was not present in the dictionary
1.描述
当连接数据库时,使用了旧的mysql.data.dll会出现此问题。
string conString = "server=localhost; user id=root; password=admin123456; database=hello; pooling=false;charset =utf8;";
MySqlConnection mySqlConnection = new MySqlConnection(conString);
if (mySqlConnection.State != ConnectionState.Open)
{
mySqlConnection.Open();
}
MySqlCommand cmd = mySqlConnection.CreateCommand();
cmd.CommandText = "select * from stu;";
MySqlDataAdapter adap = new MySqlDataAdapter(cmd);
DataTable dt = new DataTable();
adap.Fill(dt);
数据库编码已经设置为utf8。在adap.Fill(dt);语句报错。
2.解决
utf8mb4是新版本出的utf8格式,老版本的dll不支持,所以直接下载新的dll。
Nuget直接下载最新的mysql.data.dll,即可。
BUG_10:当前 .NET SDK 不支持将 .NET Core 3.1 设置为目标。请将 .NET Core 3.0或更低版本设置
1.描述
使用vs2017打开.NET Core 3.1的项目时,出现此错误。原因是2017不支持.NET Core 3.0以上的项目了。
2.解决
还是得用2019。