I'm trying to make a command line for my game in Unity and when adding system information commands like memory I encountered this problem. I hope the community can help me. Thanks in advance. The errors occur at lines 216, 223, and 225.
using UnityEngine;
using System;
using System.Collections.Generic;
using System.Text;
public delegate void CommandHandler(string[] args);
public class ConsoleController {
#region Event declarations
// Used to communicate with ConsoleView
public delegate void LogChangedHandler(string[] log);
public event LogChangedHandler logChanged;
public delegate void VisibilityChangedHandler(bool visible);
public event VisibilityChangedHandler visibilityChanged;
#endregion
/// <summary>
/// Object to hold information about each command
/// </summary>
class CommandRegistration {
public string command { get; private set; }
public CommandHandler handler { get; private set; }
public string help { get; private set; }
public CommandRegistration(string command, CommandHandler handler, string help) {
this.command = command;
this.handler = handler;
this.help = help;
}
}
/// <summary>
/// How many log lines should be retained?
/// Note that strings submitted to appendLogLine with embedded newlines will be counted as a single line.
/// </summary>
const int scrollbackSize = 20;
Queue<string> scrollback = new Queue<string>(scrollbackSize);
List<string> commandHistory = new List<string>();
Dictionary<string, CommandRegistration> commands = new Dictionary<string, CommandRegistration>();
public string[] log { get; private set; } //Copy of scrollback as an array for easier use by ConsoleView
const string repeatCmdName = "!!"; //Name of the repeat command, constant since it needs to skip these if they are in the command history
public ConsoleController() {
//When adding commands, you must add a call below to registerCommand() with its name, implementation method, and help text.
registerCommand("babble", babble, "Example command that demonstrates how to parse arguments. babble [word] [# of times to repeat]");
registerCommand("echo", echo, "echoes arguments back as array (for testing argument parser)");
registerCommand("help", help, "Print this help.");
registerCommand("hide", hide, "Hide the console.");
registerCommand(repeatCmdName, repeatCommand, "Repeat last command.");
registerCommand("reload", reload, "Reload game.");
registerCommand("resetprefs", resetPrefs, "Reset & saves PlayerPrefs.");
registerCommand("ver", ver, "Displays the current game version.");
registerCommand("buildver", buildver, "Displays the current build.");
registerCommand("sys", sys, "Displays basic system information.");
registerCommand("devinfo", devinfo, "Displays important developer information.");
}
void registerCommand(string command, CommandHandler handler, string help) {
commands.Add(command, new CommandRegistration(command, handler, help));
}
public void appendLogLine(string line) {
Debug.Log(line);
if (scrollback.Count >= ConsoleController.scrollbackSize) {
scrollback.Dequeue();
}
scrollback.Enqueue(line);
log = scrollback.ToArray();
if (logChanged != null) {
logChanged(log);
}
}
public void runCommandString(string commandString) {
appendLogLine("$ " + commandString);
string[] commandSplit = parseArguments(commandString);
string[] args = new string[0];
if (commandSplit.Length < 1) {
appendLogLine(string.Format("Unable to process command '{0}'", commandString));
return;
} else if (commandSplit.Length >= 2) {
int numArgs = commandSplit.Length - 1;
args = new string[numArgs];
Array.Copy(commandSplit, 1, args, 0, numArgs);
}
runCommand(commandSplit[0].ToLower(), args);
commandHistory.Add(commandString);
}
public void runCommand(string command, string[] args) {
CommandRegistration reg = null;
if (!commands.TryGetValue(command, out reg)) {
appendLogLine(string.Format("Unknown command '{0}', type 'help' for list.", command));
} else {
if (reg.handler == null) {
appendLogLine(string.Format("Unable to process command '{0}', handler was null.", command));
} else {
reg.handler(args);
}
}
}
static string[] parseArguments(string commandString)
{
LinkedList<char> parmChars = new LinkedList<char>(commandString.ToCharArray());
bool inQuote = false;
var node = parmChars.First;
while (node != null)
{
var next = node.Next;
if (node.Value == '"') {
inQuote = !inQuote;
parmChars.Remove(node);
}
if (!inQuote && node.Value == ' ') {
node.Value = '\n';
}
node = next;
}
char[] parmCharsArr = new char[parmChars.Count];
parmChars.CopyTo(parmCharsArr, 0);
return (new string(parmCharsArr)).Split(new char[] {'\n'} , StringSplitOptions.RemoveEmptyEntries);
}
#region Command handlers
//Implement new commands in this region of the file.
/// <summary>
/// A test command to demonstrate argument checking/parsing.
/// Will repeat the given word a specified number of times.
/// </summary>
void babble(string[] args) {
if (args.Length < 2) {
appendLogLine("Expected 2 arguments.");
return;
}
string text = args[0];
if (string.IsNullOrEmpty(text)) {
appendLogLine("Expected arg1 to be text.");
} else {
int repeat = 0;
if (!Int32.TryParse(args[1], out repeat)) {
appendLogLine("Expected an integer for arg2.");
} else {
for(int i = 0; i < repeat; ++i) {
appendLogLine(string.Format("{0} {1}", text, i));
}
}
}
}
void echo(string[] args) {
StringBuilder sb = new StringBuilder();
foreach (string arg in args)
{
sb.AppendFormat("{0},", arg);
}
sb.Remove(sb.Length - 1, 1);
appendLogLine(sb.ToString());
}
void help(string[] args) {
foreach(CommandRegistration reg in commands.Values) {
appendLogLine(string.Format("{0}: {1}", reg.command, reg.help));
}
}
void hide(string[] args) {
if (visibilityChanged != null) {
visibilityChanged(false);
}
}
void repeatCommand(string[] args) {
for (int cmdIdx = commandHistory.Count - 1; cmdIdx >= 0; --cmdIdx) {
string cmd = commandHistory[cmdIdx];
if (String.Equals(repeatCmdName, cmd)) {
continue;
}
runCommandString(cmd);
break;
}
}
void reload(string[] args) {
Application.LoadLevel(Application.loadedLevel);
}
void resetPrefs(string[] args) {
PlayerPrefs.DeleteAll();
PlayerPrefs.Save();
}
void ver(string[] args) {
appendLogLine("La Llorona 16w14~");
}
void buildver(string[] args)
{
appendLogLine("Build 040916.04");
}
void sys(string[] args)
{
appendLogLine(SystemInfo.operatingSystem);
appendLogLine(SystemInfo.processorType);
appendLogLine(SystemInfo.systemMemorySize);
appendLogLine(SystemInfo.graphicsDeviceName);
}
void devinfo(string[] args)
{
appendLogLine(SystemInfo.deviceModel);
appendLogLine(SystemInfo.deviceType);
appendLogLine(SystemInfo.graphicsDeviceName);
appendLogLine(SystemInfo.graphicsMemorySize);
}
#endregion
}
appendLogLine takes string as the parameter but you are passing int to it with appendLogLine(SystemInfo.systemMemorySize);, appendLogLine(SystemInfo.deviceType); and appendLogLine(SystemInfo.graphicsMemorySize);
You have to convert those integers to strings with ToString(). So those lines should be
appendLogLine(SystemInfo.systemMemorySize.ToString());
appendLogLine(SystemInfo.deviceType.ToString());
appendLogLine(SystemInfo.graphicsMemorySize.ToString());
Also, Application.LoadLevel(Application.loadedLevel); is deprecated so include using UnityEngine.SceneManagement; at the top then change Application.LoadLevel to
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
The fixed version of your code:
using UnityEngine;
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine.SceneManagement;
public delegate void CommandHandler(string[] args);
public class ConsoleController
{
#region Event declarations
// Used to communicate with ConsoleView
public delegate void LogChangedHandler(string[] log);
public event LogChangedHandler logChanged;
public delegate void VisibilityChangedHandler(bool visible);
public event VisibilityChangedHandler visibilityChanged;
#endregion
/// <summary>
/// Object to hold information about each command
/// </summary>
class CommandRegistration
{
public string command { get; private set; }
public CommandHandler handler { get; private set; }
public string help { get; private set; }
public CommandRegistration(string command, CommandHandler handler, string help)
{
this.command = command;
this.handler = handler;
this.help = help;
}
}
/// <summary>
/// How many log lines should be retained?
/// Note that strings submitted to appendLogLine with embedded newlines will be counted as a single line.
/// </summary>
const int scrollbackSize = 20;
Queue<string> scrollback = new Queue<string>(scrollbackSize);
List<string> commandHistory = new List<string>();
Dictionary<string, CommandRegistration> commands = new Dictionary<string, CommandRegistration>();
public string[] log { get; private set; } //Copy of scrollback as an array for easier use by ConsoleView
const string repeatCmdName = "!!"; //Name of the repeat command, constant since it needs to skip these if they are in the command history
public ConsoleController()
{
//When adding commands, you must add a call below to registerCommand() with its name, implementation method, and help text.
registerCommand("babble", babble, "Example command that demonstrates how to parse arguments. babble [word] [# of times to repeat]");
registerCommand("echo", echo, "echoes arguments back as array (for testing argument parser)");
registerCommand("help", help, "Print this help.");
registerCommand("hide", hide, "Hide the console.");
registerCommand(repeatCmdName, repeatCommand, "Repeat last command.");
registerCommand("reload", reload, "Reload game.");
registerCommand("resetprefs", resetPrefs, "Reset & saves PlayerPrefs.");
registerCommand("ver", ver, "Displays the current game version.");
registerCommand("buildver", buildver, "Displays the current build.");
registerCommand("sys", sys, "Displays basic system information.");
registerCommand("devinfo", devinfo, "Displays important developer information.");
}
void registerCommand(string command, CommandHandler handler, string help)
{
commands.Add(command, new CommandRegistration(command, handler, help));
}
public void appendLogLine(string line)
{
Debug.Log(line);
if (scrollback.Count >= ConsoleController.scrollbackSize)
{
scrollback.Dequeue();
}
scrollback.Enqueue(line);
log = scrollback.ToArray();
if (logChanged != null)
{
logChanged(log);
}
}
public void runCommandString(string commandString)
{
appendLogLine("$ " + commandString);
string[] commandSplit = parseArguments(commandString);
string[] args = new string[0];
if (commandSplit.Length < 1)
{
appendLogLine(string.Format("Unable to process command '{0}'", commandString));
return;
}
else if (commandSplit.Length >= 2)
{
int numArgs = commandSplit.Length - 1;
args = new string[numArgs];
Array.Copy(commandSplit, 1, args, 0, numArgs);
}
runCommand(commandSplit[0].ToLower(), args);
commandHistory.Add(commandString);
}
public void runCommand(string command, string[] args)
{
CommandRegistration reg = null;
if (!commands.TryGetValue(command, out reg))
{
appendLogLine(string.Format("Unknown command '{0}', type 'help' for list.", command));
}
else
{
if (reg.handler == null)
{
appendLogLine(string.Format("Unable to process command '{0}', handler was null.", command));
}
else
{
reg.handler(args);
}
}
}
static string[] parseArguments(string commandString)
{
LinkedList<char> parmChars = new LinkedList<char>(commandString.ToCharArray());
bool inQuote = false;
var node = parmChars.First;
while (node != null)
{
var next = node.Next;
if (node.Value == '"')
{
inQuote = !inQuote;
parmChars.Remove(node);
}
if (!inQuote && node.Value == ' ')
{
node.Value = '\n';
}
node = next;
}
char[] parmCharsArr = new char[parmChars.Count];
parmChars.CopyTo(parmCharsArr, 0);
return (new string(parmCharsArr)).Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
}
#region Command handlers
//Implement new commands in this region of the file.
/// <summary>
/// A test command to demonstrate argument checking/parsing.
/// Will repeat the given word a specified number of times.
/// </summary>
void babble(string[] args)
{
if (args.Length < 2)
{
appendLogLine("Expected 2 arguments.");
return;
}
string text = args[0];
if (string.IsNullOrEmpty(text))
{
appendLogLine("Expected arg1 to be text.");
}
else
{
int repeat = 0;
if (!Int32.TryParse(args[1], out repeat))
{
appendLogLine("Expected an integer for arg2.");
}
else
{
for (int i = 0; i < repeat; ++i)
{
appendLogLine(string.Format("{0} {1}", text, i));
}
}
}
}
void echo(string[] args)
{
StringBuilder sb = new StringBuilder();
foreach (string arg in args)
{
sb.AppendFormat("{0},", arg);
}
sb.Remove(sb.Length - 1, 1);
appendLogLine(sb.ToString());
}
void help(string[] args)
{
foreach (CommandRegistration reg in commands.Values)
{
appendLogLine(string.Format("{0}: {1}", reg.command, reg.help));
}
}
void hide(string[] args)
{
if (visibilityChanged != null)
{
visibilityChanged(false);
}
}
void repeatCommand(string[] args)
{
for (int cmdIdx = commandHistory.Count - 1; cmdIdx >= 0; --cmdIdx)
{
string cmd = commandHistory[cmdIdx];
if (String.Equals(repeatCmdName, cmd))
{
continue;
}
runCommandString(cmd);
break;
}
}
void reload(string[] args)
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
void resetPrefs(string[] args)
{
PlayerPrefs.DeleteAll();
PlayerPrefs.Save();
}
void ver(string[] args)
{
appendLogLine("La Llorona 16w14~");
}
void buildver(string[] args)
{
appendLogLine("Build 040916.04");
}
void sys(string[] args)
{
appendLogLine(SystemInfo.operatingSystem);
appendLogLine(SystemInfo.processorType);
appendLogLine(SystemInfo.systemMemorySize.ToString());
appendLogLine(SystemInfo.graphicsDeviceName);
}
void devinfo(string[] args)
{
appendLogLine(SystemInfo.deviceModel);
appendLogLine(SystemInfo.deviceType.ToString());
appendLogLine(SystemInfo.graphicsDeviceName);
appendLogLine(SystemInfo.graphicsMemorySize.ToString());
}
#endregion
}
Related
I am working on my own multithreading for my algorithm independed pathfinding for unity. However, when I am executing two the same class I get a memory leak and when only executing one instance I am having no issues. I really want to use at least two threads if it is necessary.
Below is the class I have issues with. Keep in mind, that two independend threads will have to execute parts of this script. AddJob can be called from the main unity thread but will most likely be called from another update thread for the agents.
namespace Plugins.PathFinding.Threading
{
internal class PathFindingThread
{
private Thread m_Worker;
private volatile Queue<CompletedProcessingCallback> m_CallbackQueue;
private volatile Queue<IAlgorithm> m_QueuedTasks;
internal int GetTaskCount
{
get
{
return m_QueuedTasks.Count;
}
}
internal PathFindingThread()
{
m_Worker = new Thread(Run);
m_CallbackQueue = new Queue<CompletedProcessingCallback>();
m_QueuedTasks = new Queue<IAlgorithm>();
}
private void Run()
{
Debug.Log("<b><color=green> [ThreadInfo]:</color></b> PathFinding Thread Started ");
try
{
while(true)
{
if (m_QueuedTasks.Count > 0)
{
IAlgorithm RunningTask = m_QueuedTasks.Dequeue();
RunningTask.FindPath(new IAlgorithmCompleted(AddCallback));
}
else
break;
}
Debug.Log("<b><color=red> [ThreadInfo]:</color></b> PathFinding Worker is idle and has been Stopped");
}
catch(Exception)
{
Debug.Log("<b><color=red> [ThreadInfo]:</color></b> PathFinding thread encountred an error and has been aborted");
}
}
internal void AddJob(IAlgorithm AlgorithmToRun)
{
m_QueuedTasks.Enqueue(AlgorithmToRun);
//Debug.Log("Added Job To Queue");
}
private void AddCallback(CompletedProcessingCallback callback)
{
m_CallbackQueue.Enqueue(callback);
}
private void Update()
{
if (m_CallbackQueue.Count > 0)
{
if (m_CallbackQueue.Peek().m_Callback != null) { }
m_CallbackQueue.Peek().m_Callback.Invoke(m_CallbackQueue.Peek().m_Path);
m_CallbackQueue.Dequeue();
}
if (m_Worker.ThreadState != ThreadState.Running && m_QueuedTasks.Count != 0)
{
m_Worker = new Thread(Run);
m_Worker.Start();
}
}
}
internal delegate void IAlgorithmCompleted(CompletedProcessingCallback callback);
internal struct CompletedProcessingCallback
{
internal volatile FindPathCompleteCallback m_Callback;
internal volatile List<GridNode> m_Path;
}
}
namespace Plugins.PathFinding
{
internal enum TypeOfNode
{
Ground,
Air
}
//used to store location information since array can only take rounded numbers
internal struct Position
{
internal int x;
internal int y;
internal int z;
}
internal class GridNode
{
internal Position M_PostitionInGrid { get; private set; }
internal Vector3 M_PostitionInWorld { get; private set; }
internal TypeOfNode M_type { get; private set; }
internal bool m_IsWalkable = true;
internal GridNode m_ParrentNode;
internal int Hcost;
internal int Gcost;
internal int Fcost { get { return Hcost + Gcost; } }
internal GridNode(Position postion , Vector3 WorldPosition)
{
M_PostitionInGrid = postion;
m_IsWalkable = true;
M_PostitionInWorld = WorldPosition;
}
}
}
internal delegate void FindPathCompleteCallback(List<GridNode> Path);
internal abstract class IAlgorithm
{
protected GridNode m_SavedStart;
protected GridNode m_SavedTarget;
protected List<GridNode> m_LocatedPath;
protected FindPathCompleteCallback m_Callback;
internal FindPathCompleteCallback GetCallback
{
get
{
return m_Callback;
}
}
protected PathFindingGrid m_grid;
internal abstract void FindPath(IAlgorithmCompleted callback);
protected abstract List<GridNode> CreatePath(PathFindingGrid Grid, GridNode Start, GridNode Target);
protected abstract List<GridNode> RetracePath(GridNode start, GridNode target);
}
namespace Plugins.PathFinding.Astar
{
internal class AstarFinder : IAlgorithm
{
//construction of the Algorithm
internal AstarFinder(GridNode start, GridNode target, FindPathCompleteCallback Callback)
{
m_SavedStart = start;
m_SavedTarget = target;
m_Callback = Callback;
m_LocatedPath = new List<GridNode>();
m_grid = PathFindingGrid.GetInstance;
}
//function to start finding a path
internal override void FindPath(IAlgorithmCompleted callback)
{
//running Algorithm and getting the path
m_LocatedPath = CreatePath(PathFindingGrid.GetInstance, m_SavedStart, m_SavedTarget);
callback.Invoke(
new CompletedProcessingCallback()
{
m_Callback = m_Callback,
m_Path = m_LocatedPath
});
}
//Algorithm
protected override List<GridNode> CreatePath(PathFindingGrid Grid, GridNode Start, GridNode Target)
{
if(Grid == null ||
Start == null ||
Target == null)
{
UnityEngine.Debug.Log("Missing Parameter, might be outside of grid");
return new List<GridNode>();
}
List<GridNode> Path = new List<GridNode>();
List<GridNode> OpenSet = new List<GridNode>();
List<GridNode> ClosedSet = new List<GridNode>();
OpenSet.Add(Start);
int Retry = 0;
while (OpenSet.Count > 0)
{
if(Retry > 3000 || Grid == null)
{
UnityEngine.Debug.Log("Path Inpossible Exiting");
break;
}
GridNode CurrentNode = OpenSet[0];
for (int i = 0; i < OpenSet.Count; i++)
{
if(OpenSet[i].Fcost < CurrentNode.Fcost || OpenSet[i].Fcost == CurrentNode.Fcost && OpenSet[i].Hcost < CurrentNode.Hcost)
{
CurrentNode = OpenSet[i];
}
}
OpenSet.Remove(CurrentNode);
ClosedSet.Add(CurrentNode);
if(CurrentNode == Target)
{
Path = RetracePath(CurrentNode,Start);
break;
}
GridNode[] neighbour = Grid.GetNeighbouringNodes(CurrentNode);
for (int i = 0; i < neighbour.Length; i++)
{
if (!neighbour[i].m_IsWalkable || ClosedSet.Contains(neighbour[i]))
continue;
int CostToNeighbour = CurrentNode.Gcost + Grid.GetDistance(CurrentNode, neighbour[i]);
if(CostToNeighbour < neighbour[i].Gcost || !OpenSet.Contains(neighbour[i]))
{
neighbour[i].Gcost = CostToNeighbour;
neighbour[i].Hcost = Grid.GetDistance(neighbour[i], Target);
neighbour[i].m_ParrentNode = CurrentNode;
if (!OpenSet.Contains(neighbour[i]))
OpenSet.Add(neighbour[i]);
}
}
Retry++;
}
return Path;
}
//retracing the path out of a node map
protected override List<GridNode> RetracePath(GridNode start, GridNode target)
{
List<GridNode> Output = new List<GridNode>();
GridNode current = start;
while(current != target)
{
Output.Add(current);
current = current.m_ParrentNode;
}
Output.Reverse();
return Output;
}
}
}
This shows the core of your code made thread safe.
internal class PathFindingThread
{
Task m_Worker;
ConcurrentQueue<CompletedProcessingCallback> m_CallbackQueue;
ConcurrentQueue<IAlgorithm> m_QueuedTasks;
internal int GetTaskCount
{
get
{
return m_QueuedTasks.Count;
}
}
internal PathFindingThread()
{
m_CallbackQueue = new ConcurrentQueue<CompletedProcessingCallback>();
m_QueuedTasks = new ConcurrentQueue<IAlgorithm>();
m_Worker = Task.Factory.StartNew(() =>
{
while (true)
{
IAlgorithm head = null;
if (m_QueuedTasks.TryDequeue(out head))
{
head.FindPath(new IAlgorithmCompleted(AddCallback));
}
else
{
Task.Delay(0);
}
}
});
}
internal void AddJob(IAlgorithm AlgorithmToRun)
{
m_QueuedTasks.Enqueue(AlgorithmToRun);
}
private void AddCallback(CompletedProcessingCallback callback)
{
m_CallbackQueue.Enqueue(callback);
}
private void Update()
{
CompletedProcessingCallback cb = null;
if (m_CallbackQueue.TryDequeue(out cb))
{
cb.m_Callback.Invoke(cb.m_Path);
}
}
}
Volatile is only good for changing the value of the field - not calling methods on a collection that is referenced by the field.
You propably do not need to have Volatile in CompletedProcessingCallback, but it depends where else this is used. Certainly having volatile on a struct field is a bad smell.
Resolve these thread issues first, then see if you still have the problem.
Basically I want to launch an event when a string reaches a specific length.
I have a Static String
Static String _Info;
So i have My Delegate that has an integer as a Parameter !
public Delegate void ReachLengthHandler(int Length);
and My event :
public event ReachLengthHandler ReachLengthEvent;
And a Method that Keep addingSome informations to that string :
public void AddInfo()
{
new Thread(() =>
{
while(true)
_Info += ""; //Basically add the inputs of the user here !
if (_Info.Length > 500)
{
if (ReachLengthEvent != null)
ReachLengthEvent(_Info.Length);
}
}).Start();
}
Do you think its the right way to do this event or there are any cleaner ways ?
EDIT :
I want this event because I want to save this string in a Database table row so I don't want to expand the possible size of a row !
As some pointed out in the comments, you may be trying to solve an instance of the XY Problem -- but assuming you're not, you are not approaching things in an object-oriented way, starting with encapsulation.
This could be a start, FWIW:
public class MaxLengthEventArgs : EventArgs
{
public MaxLengthEventArgs(string value)
{
LastAppended = value;
}
public string LastAppended { get; private set; }
}
public delegate void MaxLengthEventHandler(object sender, MaxLengthEventArgs args);
public class StringAccumulator
{
protected StringBuilder Builder { get; private set; }
public StringAccumulator(int maxLength)
{
if (maxLength < 0)
{
throw new ArgumentOutOfRangeException("maxLength", "must be positive");
}
Builder = new StringBuilder();
MaxLength = maxLength;
}
public StringAccumulator Append(string value)
{
if (!string.IsNullOrEmpty(value))
{
var sofar = value.Length + Builder.Length;
if (sofar <= MaxLength)
{
Builder.Append(value);
if ((OnMaxLength != null) && (sofar == MaxLength))
{
OnMaxLength(this, new MaxLengthEventArgs(value));
}
}
else
{
throw new InvalidOperationException("overflow");
}
}
return this;
}
public override string ToString()
{
return Builder.ToString();
}
public int MaxLength { get; private set; }
public event MaxLengthEventHandler OnMaxLength;
}
class Program
{
static void Test(object sender, MaxLengthEventArgs args)
{
var acc = (StringAccumulator)sender;
Console.WriteLine(#"max length ({0}) reached with ""{1}"" : ""{2}""", acc.MaxLength, args.LastAppended, acc.ToString());
}
public static void Main(string[] args)
{
var acc = new StringAccumulator(10);
try
{
acc.OnMaxLength += Test;
acc.Append("abc");
acc.Append("def");
acc.Append("ghij");
Console.WriteLine();
acc.Append("ouch...");
Console.WriteLine("(I won't show)");
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadKey();
}
}
Also, keep in mind that strings in .NET are immutable.
Accumulating them using string concatenation, as you did in
_Info += ""
... isn't going to scale well (performance-wise).
'HTH,
Usually eventhandler is used with specific signature.
public delegate void ReachLengthHandler(object sender, EventArgs args);
class Program
{
public event ReachLengthHandler handler;
private const int Threshhold = 500;
public string Info
{
set
{
if (value.Length > Threshhold)
{
this.OnReachLength(null);
}
}
}
public void OnReachLength(EventArgs args)
{
this.handler?.Invoke(this, args);
}
}
I am creating an application where I have a ListBox which has items that are read in from a text file using StreamReader. I have created a search form but I'm not sure what to do next. Can anyone give me some suggestions please? Here is my code:
My code for the ListBox (sorry it's so long)
public partial class frmSwitches : Form
{
public static ArrayList switches = new ArrayList();
public static frmSwitches frmkeepSwitches = null;
public static string inputDataFile = "LeckySafe.txt";
const int numSwitchItems = 6;
public frmSwitches()
{
InitializeComponent();
frmkeepSwitches = this;
}
private void btnDevices_Click(object sender, EventArgs e)
{
frmDevices tempDevices = new frmDevices();
tempDevices.Show();
frmkeepSwitches.Hide();
}
private bool fileOpenForReadOK(string readFile, ref StreamReader dataIn)
{
try
{
dataIn = new StreamReader(readFile);
return true;
}
catch (FileNotFoundException notFound)
{
MessageBox.Show("ERROR Opening file (when reading data in) - File could not be found.\n"
+ notFound.Message);
return false;
}
catch (Exception e)
{
MessageBox.Show("ERROR Opening File (when reading data in) - Operation failed.\n"
+ e.Message);
return false;
}
}
private bool getNextSwitch(StreamReader inNext, string[] nextSwitchData)
{
string nextLine;
int numDataItems = nextSwitchData.Count();
for (int i = 0; i < numDataItems; i++)
{
try
{
nextLine = inNext.ReadLine();
if (nextLine != null)
nextSwitchData[i] = nextLine;
else
{
return false;
}
}
catch (Exception e)
{
MessageBox.Show("ERROR Reading from file.\n" + e.Message);
return false;
}
}
return true;
}
private void readSwitches()
{
StreamReader inSwitches = null;
Switch tempSwitch;
bool anyMoreSwitches = false;
string[] switchData = new string[numSwitchItems];
if (fileOpenForReadOK(inputDataFile, ref inSwitches))
{
anyMoreSwitches = getNextSwitch(inSwitches, switchData);
while (anyMoreSwitches == true)
{
tempSwitch = new Switch(switchData[0], switchData[1], switchData[2], switchData[3], switchData[4], switchData[5]);
switches.Add(tempSwitch);
anyMoreSwitches = getNextSwitch(inSwitches, switchData);
}
}
if (inSwitches != null) inSwitches.Close();
}
public static bool fileOpenForWriteOK(string writeFile, ref StreamWriter dataOut)
{
try
{
dataOut = new StreamWriter(writeFile);
return true;
}
catch (FileNotFoundException notFound)
{
MessageBox.Show("ERROR Opening file (when writing data out)" +
"- File could not be found.\n" + notFound.Message);
return false;
}
catch (Exception e)
{
MessageBox.Show("ERROR Opening File (when writing data out)" +
"- Operation failed.\n" + e.Message);
return false;
}
}
public static void writeSwitches()
{
StreamWriter outputSwitches = null;
if (fileOpenForWriteOK(inputDataFile, ref outputSwitches))
{
foreach (Switch currSwitch in switches)
{
outputSwitches.WriteLine(currSwitch.getSerialNo());
outputSwitches.WriteLine(currSwitch.getType());
outputSwitches.WriteLine(currSwitch.getInsDate());
outputSwitches.WriteLine(currSwitch.getElecTest());
outputSwitches.WriteLine(currSwitch.getPatId());
outputSwitches.WriteLine(currSwitch.getNumDevice());
}
outputSwitches.Close();
}
if (outputSwitches != null) outputSwitches.Close();
}
private void showListOfSwitches()
{
lstSwitch.Items.Clear();
foreach (Switch b in switches)
lstSwitch.Items.Add(b.getSerialNo()
+ b.getType() + b.getInsDate()
+ b.getElecTest() + b.getPatId() + b.getNumDevice());
}
My code for the search form:
private void btnSearch_Click(object sender, EventArgs e)
{
frmSearchSwitch tempSearchSwitch = new frmSearchSwitch();
tempSearchSwitch.Show();
frmkeepSwitches.Hide();
}
If using a List<T> and lambda is not possible for you then go no farther.
Here I use a List<T> for the data source of a ListBox and mocked up data as where the data comes from is not important but here I am focusing on searching on a property within a class where a select is used to index the items then the where searches in this case) for a specific item, if found the index is used to move to the item. No code present for if not located as this is easy for you to do if the code here is something that is doable for you.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace ListBoxSearch_cs
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Button1_Click(object sender, EventArgs e)
{
var results =
((List<Item>)ListBox1.DataSource)
.Select((data, index) => new
{ Text = data.SerialNumber, Index = index })
.Where((data) => data.Text == "BB1").FirstOrDefault();
if (results != null)
{
ListBox1.SelectedIndex = results.Index;
}
}
private void Form1_Load(object sender, EventArgs e)
{
var items = new List<Item>() {
new Item {Identifier = 1, SerialNumber = "AA1", Type = "A1"},
new Item {Identifier = 2, SerialNumber = "BB1", Type = "A1"},
new Item {Identifier = 3, SerialNumber = "CD12", Type = "XD1"}
};
ListBox1.DisplayMember = "DisplayText";
ListBox1.DataSource = items;
}
}
/// <summary>
/// Should be in it's own class file
/// but done here to keep code together
/// </summary>
public class Item
{
public string SerialNumber { get; set; }
public string Type { get; set; }
public int Identifier { get; set; }
public string DisplayText
{
get
{
return SerialNumber + " " + this.Type;
}
}
}
}
I have an desktop console application created in visual studio 2010.How do i convert it to windows service?. basically in debug mode i want it as normal app , but in release mode i want a service build output
You can do it this way:
namespace Program
{
static class Program
{
public static bool Stopped = false;
[STAThread]
static void Main(string[] args)
{
Interactive.Initialize();
Interactive.OnStopped += new Interactive.StopedDelegate(OnStopped);
Interactive.Title = Path.GetFileNameWithoutExtension(
Assembly.GetExecutingAssembly().Location);
if (args.Length == 0) Interactive.Run(RunProc);
else if (args[0] == "-svc") ServiceBase.Run(new Service());
}
public static void RunProc() { yourConsoleMain(); }
public static void OnStopped() { Stopped = true; exitFromMain(); }
}
public class Service : ServiceBase
{
public static string Name = Path.GetFileNameWithoutExtension(
Assembly.GetExecutingAssembly().Location);
public static string CmdLineSwitch = "-svc";
public static ServiceStartMode StartMode = ServiceStartMode.Automatic;
public static bool DesktopInteract = true;
public bool Stopped = false;
public Service() { ServiceName = Name; }
public void Start() { OnStart(null); }
protected override void OnStart(string[] args)
{
System.Diagnostics.EventLog.WriteEntry(
ServiceName, ServiceName + " service started.");
Thread thread = new Thread(MainThread);
thread.Start();
}
protected override void OnStop()
{
System.Diagnostics.EventLog.WriteEntry(
ServiceName, ServiceName + " service stopped.");
Stopped = true;
Application.Exit();
}
private void MainThread()
{
Interactive.Run(Program.RunProc);
if (!Stopped) Stop();
}
}
}
Let me explain this... Basically, in Main you define that your program starts as a service if it is started with argument '-svc'.
Put in RunProc() what you normally do in main(), and in OnStopped() event handler some code that will cause main() to exit.
Then, override ServiceBase and perform some basic start/stop service.
In Windows 7 and later you must explicitly define that your service can interact with desktop if you want to see some output. But there is another problem, console window cannot be shown. So I created this console simulator which can write and also read input.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.InteropServices;
namespace ProgramIO.Control
{
public delegate void WriteDelegate(string value, int x, int y);
public delegate void ReadDelegate(out string value, bool readLine);
public delegate void EnableInputDelegate(bool enable);
public partial class InteractiveForm : Form
{
private delegate void ClearInputBufferDelegate();
public enum EIOOperation { None = 0, Write, Read }
private EventWaitHandle eventInvoke =
new EventWaitHandle(false, EventResetMode.AutoReset);
private EventWaitHandle eventInput =
new EventWaitHandle(false, EventResetMode.AutoReset);
private bool readLine = false;
private string inputBuffer = "";
private int inputPosition = 0;
private int inputBufferPosition = 0;
private EIOOperation IOOperation;
private int bufferSize = 0x10000;
private bool CaretShown = false;
private delegate object DoInvokeDelegate(Delegate method, params object[] args);
private delegate void SetTitleDelegate(string value);
private delegate void SetForegroundcolorDelegate(Color value);
public string Title {
get { return Text; }
set {
if (InvokeRequired) InvokeEx(
(SetTitleDelegate)delegate(string title) { Text = title; },
1000, new object[] { value });
else Text = value; }}
public Color ForegroundColor {
get { return ForeColor; }
set {
if (InvokeRequired) InvokeEx(
(SetForegroundcolorDelegate)delegate(Color color) { ForeColor = color; },
1000, new object[] { value });
else ForeColor = value; }}
public InteractiveForm()
{
InitializeComponent();
DoubleBuffered = true;
}
#region Asynchronous Methods
private bool InvokeEx(Delegate method, int timeout, params object[] args)
{
BeginInvoke((DoInvokeDelegate)DoInvoke, new object[] { method, args });
if (eventInvoke.WaitOne(timeout)) return true;
else return false;
}
private void EnableInput(bool enable)
{
if (InvokeRequired)
InvokeEx((EnableInputDelegate)DoEnableInput, 1000, new object[] { enable });
else DoEnableInput(enable);
}
private void ClearInputBuffer()
{
if (InvokeRequired)
InvokeEx((ClearInputBufferDelegate)DoClearInputBuffer, 1000, new object[0]);
else DoClearInputBuffer();
}
public void Write(string value, int x = -1, int y = -1)
{
lock (this) {
IOOperation = EIOOperation.Write;
if (InvokeRequired)
InvokeEx((WriteDelegate)DoWrite, 1000, new object[] { value, x, y });
else DoWrite(value, x, y);
IOOperation = EIOOperation.None; }
}
public string Read(bool readLine)
{
lock (this) {
EnableInput(true);
IOOperation = EIOOperation.Read; this.readLine = readLine; string value = "";
ClearInputBuffer(); eventInput.WaitOne();
object[] args = new object[] { value, readLine };
if (InvokeRequired) {
InvokeEx((ReadDelegate)DoRead, 1000, args); value = (string) args[0]; }
else DoRead(out value, readLine);
//inputPosition = textBox.Text.Length; inputBuffer = "";
ClearInputBuffer();
IOOperation = EIOOperation.None;
EnableInput(false);
return value;
}
}
#endregion //Asynchronous Methods
#region Synchronous Methods
protected override void OnShown(EventArgs e) { base.OnShown(e); textBox.Focus(); }
public object DoInvoke(Delegate method, params object[] args)
{
object obj = method.DynamicInvoke(args);
eventInvoke.Set();
return obj;
}
private void CorrectSelection()
{
if (textBox.SelectionStart < inputPosition) {
if (textBox.SelectionLength > (inputPosition - textBox.SelectionStart))
textBox.SelectionLength -= inputPosition - textBox.SelectionStart;
else textBox.SelectionLength = 0;
textBox.SelectionStart = inputPosition; }
}
protected void DoClearInputBuffer()
{
inputPosition = textBox.Text.Length; inputBuffer = "";
}
protected void DoEnableInput(bool enable)
{
if (enable) { textBox.ReadOnly = false; textBox.SetCaret(true); }
else { textBox.ReadOnly = true; textBox.SetCaret(false); }
}
protected void DoWrite(string value, int x, int y)
{
string[] lines = textBox.Text.Split(new string[] { "\r\n" }, StringSplitOptions.None);
string[] addLines = new string[0];
if (y == -1) y = lines.Length - 1;
if (lines.Length - 1 < y) addLines = new string[y - lines.Length - 1];
if (y < lines.Length) {
if (x == -1) x = lines[y].Length;
if (lines[y].Length < x)
lines[y] += new String(' ', x - lines[y].Length) + value;
else
lines[y] = lines[y].Substring(0, x) + value +
((x + value.Length) < lines[y].Length ?
lines[y].Substring(x + value.Length) : ""); }
else {
y -= lines.Length;
if (x == -1) x = addLines[y].Length;
addLines[y] += new String(' ', x - addLines[y].Length) + value; }
textBox.Text = (string.Join("\r\n", lines) +
(addLines.Length > 0 ? "\r\n" : "") + string.Join("\r\n", addLines));
textBox.Select(textBox.Text.Length, 0); textBox.ScrollToCaret();
inputBuffer = "";
}
protected void DoRead(out string value, bool readLine)
{
value = "";
if (readLine) {
int count = inputBuffer.IndexOf("\r\n");
if (count > 0) { value = inputBuffer.Substring(0, count); }}
else if (inputBuffer.Length > 0) {
value = inputBuffer.Substring(0, 1); }
inputBuffer = "";
}
private void textBox_TextChanged(object sender, EventArgs e)
{
if (IOOperation == EIOOperation.Read) {
inputBuffer = textBox.Text.Substring(inputPosition);
if (!readLine || inputBuffer.Contains("\r\n")) eventInput.Set(); }
if (textBox.Text.Length > bufferSize) { textBox.Text =
textBox.Text.Substring(textBox.Text.Length - bufferSize, bufferSize);
textBox.Select(textBox.Text.Length, 0); textBox.ScrollToCaret(); }
}
private void textBox_KeyDown(object sender, KeyEventArgs e)
{
if (IOOperation != EIOOperation.Read ||
(e.KeyCode == Keys.Back && inputBuffer.Length == 0))
e.SuppressKeyPress = true;
}
private void textBox_MouseUp(object sender, MouseEventArgs e)
{
CorrectSelection();
}
private void textBox_KeyUp(object sender, KeyEventArgs e)
{
if (!(IOOperation == EIOOperation.Read) ||
((e.KeyCode == Keys.Left || e.KeyCode == Keys.Up) &&
textBox.SelectionStart < inputPosition))
CorrectSelection();
}
private void InteractiveForm_FormClosing(object sender, FormClosingEventArgs e)
{
eventInput.Set();
lock (this) { }
}
#endregion //Synchronous Methods
}
public class InteractiveWindow : TextBox
{
[DllImport("user32.dll")]
static extern bool HideCaret(IntPtr hWnd);
[DllImport("user32.dll")]
static extern bool ShowCaret(IntPtr hWnd);
private delegate void SetCaretDelegate(bool visible);
private const int WM_SETFOCUS = 0x0007;
private bool CaretVisible = true;
public void SetCaret(bool visible)
{
if (InvokeRequired) Invoke((SetCaretDelegate)DoSetCaret, new object[] { visible });
else DoSetCaret(visible);
}
private void DoSetCaret(bool visible)
{
if (CaretVisible != visible)
{
CaretVisible = visible;
if (CaretVisible) ShowCaret(Handle);
else HideCaret(Handle);
}
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_SETFOCUS)
{
if (CaretVisible) { ShowCaret(Handle); }
else HideCaret(Handle);
}
}
}
}
namespace ProgramIO
{
using ProgramIO.Control;
public static class Interactive
{
public delegate void StopedDelegate();
public delegate void RunDelegate();
public static bool Initialized = false;
private static InteractiveForm frmIO = null;
private static Thread IOThread = null;
private static EventWaitHandle EventStarted =
new EventWaitHandle(false, EventResetMode.AutoReset);
public static string Title {
get { return frmIO.Title; }
set { frmIO.Title = value; } }
public static Color ForegroundColor {
get {return frmIO.ForeColor; }
set { frmIO.ForeColor = value; } }
public static event StopedDelegate OnStopped = null;
private static void form_Show(object sender, EventArgs e)
{
frmIO = sender as InteractiveForm;
EventStarted.Set();
}
private static void form_FormClosed(object sender, FormClosedEventArgs e)
{
lock (frmIO) {
frmIO = null;
Application.Exit(); }
}
public static void Initialize()
{
IOThread = new Thread(IOThreadProc);
IOThread.Name = "Interactive Thread"; IOThread.Start();
EventStarted.WaitOne();
Initialized = true;
}
public static void Run(RunDelegate runProc = null)
{
if (!Initialized) Initialize();
if (runProc != null) runProc();
Application.Run();
if (OnStopped != null) OnStopped();
}
public static void IOThreadProc()
{
InteractiveForm form = new InteractiveForm();
form.Shown += new EventHandler(form_Show);
form.FormClosed += new FormClosedEventHandler(form_FormClosed);
Application.Run(form);
}
public static void Write(string value, int x = -1, int y = -1)
{
if (frmIO != null) lock (frmIO) { frmIO.Write(value, x, y); }
}
public static void WriteLine(string value)
{
if (frmIO != null) lock (frmIO) {
Interactive.Write(value); Interactive.Write("\r\n"); }
}
public static int Read()
{
if (frmIO != null) lock (frmIO) {
string input = frmIO.Read(false);
if (input.Length > 0) return input[0]; }
return 0;
}
public static string ReadLine()
{
if (frmIO != null) lock (frmIO) { return frmIO.Read(true); }
else return "";
}
}
}
This last class, Interactive, actually serve as invoker for asynchronous methods, and it is used in Main() at the beginning.
You can skip this whole second section of code if you don't want to see console window when program is run as a windows service.
I have also created an Installer class for this, but it would be just to much code on this page.
EDIT: This InteractiveForm is actually a form with designer class, but very simple, consisting only of Form and EditBox inside filling its area.
Basicallly you need 3 projects in your solution:
Application itself
WinService for production
Console Application for test purposes
So your application must have some kind of Start() method with e.g. infinite loop that does all work and maybe Stop() method to stop processing.
Winservice project must contain class derived from ServiceBase, it'l have OnStartmethod that calls your application's Start and OnStop that calls application's Stop method.
Next, in console application you do pretty much same - calling Start method in console's entry point.
So far for debug you run your console app, and for release you publish your winservice project
Winservice class might look like:
upd
Winservice codez:
public class MyWinService : ServiceBase
{
IMyApplicationService _myApplicationService;
//constructor - resolve dependencies here
public MyWinService()
{
_myApplicationService = new MyApplicationService();
}
protected override void OnStart(string[] args)
{
base.OnStart(args);
try
{
_myApplicationService.Start();
}
catch (Exception exception)
{
//log exception
}
}
protected override void OnStop()
{
base.OnStop();
try
{
_myApplicationService.Stop();
}
catch (Exception exception)
{
//log exception
}
}
}
Application service:
public class MyApplicationService : IMyApplicationService
{
public MyApplicationService()
{
//some initializations
}
public Start()
{
//do work here
}
public Stop()
{
//...
}
}
I have a program that when the user says "Start" or "Stop", the program makes a skeleton display on the screen. I use the same code as the Shape Game, and it works fine there, but not on my code. I dont know which part of the code doesn't work since this is my first time eith speech recognition programming. Thanks for your help(Sorry if my code is messy)Recognizing the Speech
public class SpeechRecognizer : IDisposable
{
private KinectAudioSource kinectAudioSource;
private struct WhatSaid
{
public Verbs Verb;
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
this.Stop();
if (this.sre != null)
{
// NOTE: The SpeechRecognitionEngine can take a long time to dispose
// so we will dispose it on a background thread
ThreadPool.QueueUserWorkItem(
delegate(object state)
{
IDisposable toDispose = state as IDisposable;
if (toDispose != null)
{
toDispose.Dispose();
}
},
this.sre);
this.sre = null;
}
this.isDisposed = true;
}
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
public EchoCancellationMode EchoCancellationMode
{
get
{
this.CheckDisposed();
return this.kinectAudioSource.EchoCancellationMode;
}
set
{
this.CheckDisposed();
this.kinectAudioSource.EchoCancellationMode = value;
}
}
public static SpeechRecognizer Create()
{
SpeechRecognizer recognizer = null;
try
{
recognizer = new SpeechRecognizer();
}
catch (Exception)
{
// speech prereq isn't installed. a null recognizer will be handled properly by the app.
}
return recognizer;
}
private void CheckDisposed()
{
if (this.isDisposed)
{
throw new ObjectDisposedException("SpeechRecognizer");
}
}
public void Stop()
{
this.CheckDisposed();
if (this.sre != null)
{
this.kinectAudioSource.Stop();
this.sre.RecognizeAsyncCancel();
this.sre.RecognizeAsyncStop();
this.sre.SpeechRecognized -= this.SreSpeechRecognized;
this.sre.SpeechHypothesized -= this.SreSpeechHypothesized;
this.sre.SpeechRecognitionRejected -= this.SreSpeechRecognitionRejected;
}
}
public void Start(KinectAudioSource kinectSource)
{
this.CheckDisposed();
this.kinectAudioSource = kinectSource;
this.kinectAudioSource.AutomaticGainControlEnabled = false;
this.kinectAudioSource.BeamAngleMode = BeamAngleMode.Adaptive;
var kinectStream = this.kinectAudioSource.Start();
this.sre.SetInputToAudioStream(
kinectStream, new SpeechAudioFormatInfo(EncodingFormat.Pcm, 16000, 16, 1, 32000, 2, null));
this.sre.RecognizeAsync(RecognizeMode.Multiple);
}
public enum Verbs
{
None = 0,
Start,
Stop,
Resume,
Pause
}
private bool isDisposed;
private readonly Dictionary<string, WhatSaid> speechCommands = new Dictionary<string, WhatSaid>
{
{ "Start", new WhatSaid { Verb = Verbs.Start } },
{ "Stop", new WhatSaid { Verb = Verbs.Stop } },
{ "Resume", new WhatSaid { Verb = Verbs.Resume } },
{ "Pause", new WhatSaid { Verb = Verbs.Pause } },
};
private SpeechRecognitionEngine sre;
private static RecognizerInfo GetKinectRecognizer()
{
Func<RecognizerInfo, bool> matchingFunc = r =>
{
string value;
r.AdditionalInfo.TryGetValue("Kinect", out value);
return "True".Equals(value, StringComparison.InvariantCultureIgnoreCase) && "en-US".Equals(r.Culture.Name, StringComparison.InvariantCultureIgnoreCase);
};
return SpeechRecognitionEngine.InstalledRecognizers().Where(matchingFunc).FirstOrDefault();
}
private SpeechRecognizer()
{
RecognizerInfo ri = GetKinectRecognizer();
this.sre = new SpeechRecognitionEngine(ri);
this.LoadGrammar(this.sre);
}
private void LoadGrammar(SpeechRecognitionEngine speechRecognitionEngine)
{
// Build a simple grammar of shapes, colors, and some simple program control
var single = new Choices();
foreach (var phrase in this.speechCommands)
{
single.Add(phrase.Key);
}
var objectChoices = new Choices();
objectChoices.Add(single);
var actionGrammar = new GrammarBuilder();
actionGrammar.AppendWildcard();
actionGrammar.Append(objectChoices);
var allChoices = new Choices();
allChoices.Add(actionGrammar);
allChoices.Add(single);
// This is needed to ensure that it will work on machines with any culture, not just en-us.
var gb = new GrammarBuilder { Culture = speechRecognitionEngine.RecognizerInfo.Culture };
gb.Append(allChoices);
var g = new Grammar(gb);
speechRecognitionEngine.LoadGrammar(g);
speechRecognitionEngine.SpeechRecognized += this.SreSpeechRecognized;
speechRecognitionEngine.SpeechHypothesized += this.SreSpeechHypothesized;
speechRecognitionEngine.SpeechRecognitionRejected += this.SreSpeechRecognitionRejected;
}
private void SreSpeechRecognitionRejected(object sender, SpeechRecognitionRejectedEventArgs e)
{
var said = new SaidSomethingEventArgs { Verb = Verbs.None, Matched = "?" };
this.SetLabel("Word not Recognized.... Try 'Start', 'Stop', 'Pause' or 'Resume'");
if (this.SaidSomething != null)
{
this.SaidSomething(new object(), said);
}
}
private void SreSpeechHypothesized(object sender, SpeechHypothesizedEventArgs e)
{
this.SetLabel("I think you said: " + e.Result.Text);
}
public event EventHandler<SaidSomethingEventArgs> SaidSomething;
private void SreSpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
this.SetLabel("\rSpeech Recognized: \t" + e.Result.Text);
if ((this.SaidSomething == null) || (e.Result.Confidence < 0.3))
{
return;
}
var said = new SaidSomethingEventArgs { Verb = 0, Phrase = e.Result.Text };
foreach (var phrase in this.speechCommands)
{
if (e.Result.Text.Contains(phrase.Key) && (phrase.Value.Verb == Verbs.Pause))
{
//pause = true;
break;
}
else if ((e.Result.Text.Contains(phrase.Key) && (phrase.Value.Verb == Verbs.Resume)))
{
//resume = true;
break;
}
else if ((e.Result.Text.Contains(phrase.Key) && (phrase.Value.Verb == Verbs.Start)))
{
//start = true;
break;
}
else if ((e.Result.Text.Contains(phrase.Key) && (phrase.Value.Verb == Verbs.Stop)))
{
//stop = true;
break;
}
}
// Look for a match in the order of the lists below, first match wins.
List<Dictionary<string, WhatSaid>> allDicts = new List<Dictionary<string, WhatSaid>> { this.speechCommands };
bool found = false;
for (int i = 0; i < allDicts.Count && !found; ++i)
{
foreach (var phrase in allDicts[i])
{
if (e.Result.Text.Contains(phrase.Key))
{
found = true;
break;
}
}
}
if (!found)
{
return;
}
}
public class SaidSomethingEventArgs : EventArgs
{
public Verbs Verb { get; set; }
public string Phrase { get; set; }
public string Matched { get; set; }
}
public event Action<string> SetLabel = delegate { };
}
In my Code
private void RecognizeSaidSomething(object sender, SpeechRecognizer.SpeechRecognizer.SaidSomethingEventArgs e)
{
FlyingText.FlyingText.NewFlyingText(this.skeleton.Width / 30, new Point(this.skeleton.Width / 2, this.skeleton.Height / 2), e.Matched);
switch (e.Verb)
{
case SpeechRecognizer.SpeechRecognizer.Verbs.Pause:
pause = true;
break;
case SpeechRecognizer.SpeechRecognizer.Verbs.Resume:
resume = true;
break;
case SpeechRecognizer.SpeechRecognizer.Verbs.Start:
start = true;
break;
case SpeechRecognizer.SpeechRecognizer.Verbs.Stop:
stop = true;
break;
}
}
It doesn't look like you ever call RecognizeSaidSomething() from SreSpeechRecognized(). You create the event args:
var said = new SaidSomethingEventArgs { Verb = 0, Phrase =
e.Result.Text };
But it doesn't appear that you do anything with it.
The foreach loop below that doesn't seem to serve any purpose, you test for the phrase then just break out of the loop. You don't set any variables or call any functions in that loop that I can see.
Then there is a for loop that appears to do something similar to the foreach loop (just in a different manner). It searches for matches to the recognized phrase, but then doesn't do anything with what it finds. It just returns.
I would think somewhere in the SreSpeechRecognized() event handler you want to call RecognizeSaidSomething() and pass it the SaidSomethingEventArgs.