Author Topic: VA.CommandsStopped Explanation  (Read 5440 times)

Exergist

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 405
  • Ride the lightning
VA.CommandsStopped Explanation
« on: February 13, 2019, 09:40:59 PM »
In v1.7.3.1 Gary introduced...
Quote
'CommandsStopped' event to the proxy object for use within inline functions so that your inline function can be notified when the, 'Stop All Commands' action has been executed (or the button on the main screen has been pressed).

Below is an example of that functionality in action.

Referenced Assemblies: System.dll

Code: [Select]
using System;

public class VAInline
{
public Boolean _stop = false; // Initialize boolean variable indicating stop state

public void main()
{
VA.CommandsStopped += CommandsStoppedAction; // Subscribe to event where a "Stop All Commands" action is executed (or Stop button is pressed)

VA.WriteToLog("Start looping", "purple"); // Output info to event log
while(!_stop) // Loop while stop state is false
{
VA.WriteToLog("looping", "orange"); // Output info to event log
System.Threading.Thread.Sleep(250); // Brief pause (in milliseconds)
}
VA.WriteToLog("Exited loop", "purple"); // Output info to event log
_stop = false; // Set boolean variable back to starting state
}

public void CommandsStoppedAction()
{
VA.CommandsStopped -= CommandsStoppedAction; // Unsubscribe from "Stop Commands" events
_stop = true; // Change boolean variable to track that a "Stop Commands" action took place
VA.WriteToLog("Command stopped, so, let's stop too.", "pink"); // Output info to event log
}
}

Gary gets the majority of the credit for this code. I just made a few tweaks to improve it for visual demonstration and added the comments.

Here is the associated event log output (I pressed the Stop Commands button shortly after firing the command):



So if you subscribe to the VA.CommandsStopped event and then execute a "Stop Commands" action (or press the Stop Commands button), then the event handler function (in this case CommandsStoppedAction) will be immediately called. From there you can add whatever code you need to properly handle the action, which I'm guessing for most cases will be inline function "close out" work for a more graceful exit.

I've also included a line for unsubscribing from the CommandsStopped event (learn more here). Enjoy! :)



UPDATE

In case you need to use VA.CommandsStopped outside of the VAInline class you'll have to do a bit more legwork. Kudos to Gary for helping test out the use of VoiceAttack.VoiceAttackInitProxyClass for this application. Here is a brief example showing how to subscribe to CommandsStopped events while a form (created in a separate class) is displayed.

Referenced Assemblies: Microsoft.CSharp.dll; System.dll; System.Core.dll; System.Windows.Forms.dll

Code: [Select]
using System;
using System.Windows.Forms;
using System.Threading;

class VAInline
{
void main()
{
// stuff...

Thread t = new Thread(() => { Application.Run(new MyClass(VA)); }); // Set work for thread t to create new instance of MyClass and open a message loop
t.Start(); // Start thread t
try // Attempt the following code...
{
if (Thread.CurrentThread != t) // Check that current thread and t are different
t.Join(); // Blocks current thread until thread t terminates
}
catch {} // Handle exceptions encountered during "try." In this case do nothing.
finally
{
// more closeup stuff
}

// more stuff...
}
}

class MyClass : Form
{
// Declare important variables for this form
VoiceAttack.VoiceAttackInitProxyClass VA_Proxy;
dynamic VA;

// Create and display YourClass
public MyClass(dynamic myVA)
{
// Define VA and VA_Proxy based on info passed in during call
VA = myVA;
VA_Proxy = myVA;

// stuff...

VA_Proxy.CommandsStopped += CommandsStoppedAction; // Subscribe to event where a "Stop Commands" action is executed (or Stop Button is pressed)

// more stuff...
}

private void CommandsStoppedAction()
{
VA.WriteToLog("Command stopped, so, let's stop too.", "pink"); // Output info to event log
VA_Proxy.CommandsStopped -= CommandsStoppedAction; // Unsubscribe from "Stop Commands" events
this.Close(); // Close the form gracefully
}
}

I'm using both VoiceAttack.VoiceAttackInitProxyClass VA_Proxy and dynamic VA in MyClass because VoiceAttack.VoiceAttackInitProxyClass doesn't appear to support all the typical functionality available to dynamic VA (I've only found an issue with VA_Proxy.ParseTokens so far, though other functions may also not work).

Executing a "Stop Commands" action seems to kill the thread the inline function runs on. If the form is launched on the main inline thread then a fatal error sometimes occurs after the form is closed (I don't have a good explanation for this). To get around this I've elected to create the form using a second thread. When the second thread terminates after the form is closed, often the timing of everything causes t.Join to produce an error (since usually the main thread is gone by this point). When this happens only the remaining code in the catch and finally blocks will execute.

@Gary please comment if anything I've described is inaccurate.
« Last Edit: April 29, 2019, 10:44:35 AM by Exergist »

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4782
  • RTFM
Re: VA.CommandsStopped Explanation
« Reply #1 on: February 13, 2019, 11:08:41 PM »
This is more efficient than checking the VA.Stopped property in a loop as well, though the real-world effect is negligible:

Code: [Select]
using System;
using System.Diagnostics;

public class VAInline
{
public void main()
{
bool stop = false;

Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();

for (int i = 0; i < 1000000; i++)
{
if (VA.Stopped)
{
return;
}
}

stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
VA.WriteToLog("VA.Stopped: " + ts.TotalMilliseconds + "ms");
stopWatch.Restart();

for (int i = 0; i < 1000000; i++)
{
if (stop)
{
return;
}
}

stopWatch.Stop();
ts = stopWatch.Elapsed;
VA.WriteToLog("bool: " + ts.TotalMilliseconds + "ms");
}
}

On my machine running the check one million times with VA.Stopped takes ~19.1ms, whereas checking the boolean takes ~0.26ms.


Exergist

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 405
  • Ride the lightning
Re: VA.CommandsStopped Explanation
« Reply #2 on: February 17, 2019, 12:06:16 AM »
I updated the original post to include an example for using CommandsStopped outside of VAInline (i.e., in another class).