今天在实验Lua+WPF的时候碰到一个问题:
我在主线程中写的LUA虚拟机的 dofile,但当我要令LUA脚本执行阻塞的时候,同时也会阻塞UI线程。
于是我把对LUA的接口挪到另一个单独的后台线程中,专门负责与LUA脚本的交互。
编译一切正常,运行时THROW了异常,说不能在非创建UI元素的线程中改变UI元素属性。。
查了一下,C#就是这种机制,因为其GUI系统底层是内部单线程机制,所以为了避免各种乱七八糟的错误,直接禁用了跨线程的GUI元素操作。
查了一下,用了个Dispatcher的叫 “BeginInvoke” 的方法解决本问题。
其思想也就是异步调用,不过我估计是从GUI元素的dispatcher上分出时间片来启动线程。(没有深研究,不过总算搞定了这个问题)
主要代码如下,被注掉的部分是原来行不通的方法。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using LuaInterface;
namespace CodersLife
{
/// <summary>
/// 工具类
/// </summary>
class Super
{
/// <summary>
/// 加载图片
/// </summary>
/// <param name="address">图片地址</param>
/// <returns>图片</returns>
static public BitmapSource GetImage(string address)
{
return new BitmapImage(new Uri(AppDomain.CurrentDomain.BaseDirectory + string.Format("/Resource/Image/{0}", address), UriKind.Relative));
}
}
/// <summary>
/// LuaAPI类
/// </summary>
class LuaAPI
{
public Lua lua = new Lua();//初始化lua虚拟机
//public Thread luaThread;
public Window1 MainWindow { get; set; }
public void Start()
{
try
{
//绑定lua函数
lua.RegisterFunction("BackImage", this, this.GetType().GetMethod("BackImage"));
lua.RegisterFunction("Music", this, this.GetType().GetMethod("Music"));
lua.RegisterFunction("Debug", this, this.GetType().GetMethod("Debug"));
lua.RegisterFunction("BindRolePic", this, this.GetType().GetMethod("BindRolePic"));
lua.RegisterFunction("Dialog", this, this.GetType().GetMethod("Dialog"));
//启动lua脚本
lua.DoFile("Script/Test.lua");
}
catch (System.Exception e)
{
MessageBox.Show(e.ToString());
}
}
//切换游戏背景图片
public void BackImage(string image)
{
Brush brushInstance = new ImageBrush { ImageSource = Super.GetImage(image) };
MainWindow.Carrier.Background = brushInstance;
}
//切换音乐
public void Music(string music)
{
try
{
MainWindow.BackMusic.Stop();
MainWindow.BackMusic.Source = new Uri(AppDomain.CurrentDomain.BaseDirectory + string.Format("/Resource/Music/{0}", music), UriKind.Relative);
MainWindow.BackMusic.Play();
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
}
private Dictionary<string, BitmapSource> _rolePic = new Dictionary<string, BitmapSource>();
//绑定角色图片
public void BindRolePic(string name, string pic)
{
_rolePic.Add(name, Super.GetImage(pic));
}
//显示角色对话
public void Dialog(string name, string dialog)
{
BitmapSource Pic = _rolePic[name];
MainWindow.DialogInfo.Content = dialog;
MainWindow.RoleName.Content = name;
Brush brushInstance = new ImageBrush { ImageSource = Pic };
MainWindow.RoleHeadPic.Background = brushInstance;
}
//debug
public void Debug(string info)
{
MessageBox.Show("debug info:" + info);
}
}
/// <summary>
/// Window1.xaml 的交互逻辑
/// </summary>
public partial class Window1 : Window
{
LuaAPI luaApi = new LuaAPI();
public delegate void LuaThreadDelegate();
public Window1()
{
InitializeComponent();
InitLua();
}
//初始化lua
public void InitLua()
{
//luaApi.luaThread = new Thread(new ThreadStart(luaApi.Start));
luaApi.MainWindow = this;
//luaApi.luaThread.Start();
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new LuaThreadDelegate(luaApi.Start));
}
//循环播放音乐
public void ReplayMusic(object sender, EventArgs e)
{
BackMusic.Stop();
BackMusic.Play();
}
}
}
分享到:
相关推荐
WPF实现一个按钮,内容是数字,利用绑定 线程可以增加按钮数字 点击按钮也可以增加数字 退出不报错。
使用WPF控件编程使用WPF控件编程使用WPF控件编程
WPF 使用线程更新绑定数据的UI控件值,从而使得界面不卡顿。
WPF获取DataTemplate里的控件的内容 源代码
wpf控件简单布局wpf控件简单布局wpf控件简单布局
wpf 二种方式绑定控件wpf 二种方式绑定控件wpf 二种方式绑定控件wpf 二种方式绑定控件wpf 二种方式绑定控件wpf 二种方式绑定控件
WPF查找一个控件下的子控件,仅限参考使用
WPF后台线程更新UI---http://www.tuicool.com/articles/NbieE3M
WPF控件内容模型主要指派生于System.Windows.Controls.Control类的各种控件,其主要分为四部分: • ContentControl • HeaderedContendControl • ItemsControl • HeaderedItemsControl 其继承关系请参考我上...
wpf界面上 控件拖动,以及控件之间的位置对换
wpf 导航条 自定义控件 ! NavigationBar
WPF实现控件的移动操作,实现大小拖动,位置移动,简单易学
WPF自定义时间控件,可选择日期、时间
WebView2为WPF网页浏览工具,具有简单易用,页面显示清晰的优点。 但是,由于微软设计缺陷,无法进行分层界面设计,顶层控件会被遮挡住。 本样例很好的解决了上述问题,实现界面的分层控制,能够正常显示顶层控件。...
wpf在RichTextBox中添加控件未启用
由于在.net平台下Winform、wpf禁止跨线程直接访问控件,因此在必须跨线程访问控件的时候采用异步方式。 1、winform项目中跨线程访问控件: 编写一个Winform小实例:在做winform项目中,有时为了将系统运行的状态实时...
使用附加属性将各种控件拖动改变大小功能整合到一起,提高复用性和移植性,界面和逻辑分离,支持自定义拖动样式。原文链接:https://blog.csdn.net/u013113678/article/details/121719278
WPF自带的控件中只有Datepicker这个控件,不足以满足功能,鉴于WPF强大的自定义控件Usercontrol的功能,所以修改了一个支持选择日期时间控件---DateTimePicker,
WPF多线程Dome实例,多线程的介绍和操作
一个WPF多线程实例:两个列表listbox,每秒从第一个列表中随机抽取出一项,然后添加到第二个列表中,同时界面实现实时更新