我在C#中有一个虚拟机,它有两个构造函数重载,五个事件处理函数和两个公共属性。我已经将这个虚拟机集成到了WinForms和Silverlight应用程序中,甚至可以在客户端/服务器设置中将其用作Web应用程序。在WinRT中集成虚拟机
界面如下:
构造
public Engine(Stream gameFile) { .. }
public Engine(Stream gameFile, Stream saveFile) { .. }
活动
public OutputReady(object sender, OutputReadyEventArgs e);
public LineWanted(object sender, LineWantedEventArgs e);
public KeyWanted(object sender, KeyWantedEventArgs e);
public SaveRequested(object sender, SaveRestoreEventArgs e);
public LoadRequested(object sender, SaveRestoreEventArgs e);
属性
public Dictionary<string, string> ChanneData { get; set; }
public byte[] SaveData { get; set; }
当WinForms和Silverlight中实现这一点,我不得不使用Invoke或类似的方法写入UI线程。
在WinRT中,UI和后台线程之间的切换隐藏在异步/等待和任务处理的后面,并且我还没有真正能够以我想要的方式移植我的虚拟机....作为服务。
我可以在我的应用程序的MainForm中嵌入虚拟机,就像我在Silverlight中完成的那样,但是我想要更多的MVC/Service实现。我想将虚拟机移除到一个具有简单界面的服务,用于启动游戏,发送新命令,保存游戏和加载游戏。 MainForm不应该知道有关vm实现的任何信息。
我已经解决了这个问题超过了几个小时,但仍然没有足够清楚的理解async/await和Tasks来完成它,以便它能正常工作。我可以让引擎启动并发送命令,但保存和加载失败,我认为这是因为异步的东西无法正常工作。
的WinForms简单的实现:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using System.Threading;
using FyreVM;
namespace FyreVMTest
{
public partial class MainForm : Form
{
private Thread vmThread = null;
private Engine vm = null;
private AutoResetEvent inputReadyEvent = new AutoResetEvent(false);
private string command = "";
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
Assembly assembly = Assembly.GetExecutingAssembly();
Stream stream =
assembly.GetManifestResourceStream("FyreVMTest.Game.shadow-w8.ulx");
vm = new Engine(stream);
vm.KeyWanted += vm_KeyWanted;
vm.LineWanted += vm_LineWanted;
vm.LoadRequested += vm_LoadRequested;
vm.OutputReady += vm_OutputReady;
vm.SaveRequested += vm_SaveRequested;
vmThread = new Thread(VMThreadProc);
vmThread.IsBackground = true;
vmThread.Start();
}
private void VMThreadProc(object dummy)
{
try
{
vm.Run();
this.Invoke(new Action(GameFinished));
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void GameFinished()
{
this.Close();
}
private void RequestLine()
{
CommandLine.Focus();
}
private void vm_LineWanted(object sender, LineWantedEventArgs e)
{
this.Invoke(new Action(RequestLine));
inputReadyEvent.WaitOne();
e.Line = command;
}
private void vm_KeyWanted(object sender, KeyWantedEventArgs e)
{
//this.Invoke(new Action(RequestKey));
//inputReadyEvent.WaitOne();
//e.Char = entry[0];
}
private void vm_OutputReady(object sender, OutputReadyEventArgs e)
{
this.Invoke(new Action<Dictionary<string,string>>(HandleOutput), e.Package);
}
private void vm_SaveRequested(object sender, SaveRestoreEventArgs e)
{
e.Stream = (Stream)this.Invoke(new Func<Stream>(RequestSaveStream));
}
private void vm_LoadRequested(object sender, SaveRestoreEventArgs e)
{
e.Stream = (Stream)this.Invoke(new Func<Stream>(RequestLoadStream));
}
private Stream RequestSaveStream()
{
using (SaveFileDialog dlg = new SaveFileDialog())
{
dlg.Title = "Select Save File";
dlg.Filter = "Textfyre save files (*.tfq)|*.tfq";
if (dlg.ShowDialog() == DialogResult.Cancel)
return null;
else
{
return new FileStream(dlg.FileName,
FileMode.Create,FileAccess.Write);
}
}
}
private Stream RequestLoadStream()
{
using (OpenFileDialog dlg = new OpenFileDialog())
{
dlg.Title = "Load a Saved Game";
dlg.Filter = "Textfyre save files (*.tfq)|*.tfq";
if (dlg.ShowDialog() == DialogResult.Cancel)
return null;
else
{
return new FileStream(dlg.FileName, FileMode.Open, FileAccess.Read);
}
}
}
private void HandleOutput(Dictionary<string, string> package)
{
MainOutput.Clear();
foreach (string key in package.Keys)
{
MainOutput.AppendText(key + ": " + package[key]);
}
}
private void GoButton_Click(object sender, EventArgs e)
{
command = CommandLine.Text;
CommandLine.Text = "";
inputReadyEvent.Set();
}
}
}
所以我正在寻找指导如何实现这个在WinRT中。接口是一个问题,还是我需要将其更改为WinRT更友好?如果没关系,在一个类中实现它的最好方法是什么,然后如何从MainForm调用该类?
任何指导非常感谢。
如果有帮助,一个示例非工作项目在这里:https://github.com/ChicagoDave/FyreXaml/ –