Im new to C#!
So my Problem: I got a C# Demo Program from an extern company, the program sets the settings of an extern device, than initialize it and starts recording the Data. The Data is written into the Console and streamed into a CSV at a Location i can choose. After pressing a Key in the Console the Recording stops. I am trying now to write a short GUI that starts and stops this Recording.
What I did:
I converted the main-method, which started the recoding, into a normal static method and deleted all writelines so the console doesnt start, than I created a Windows Form with 2 Buttons, one Start and One Stop. If I press Start, the Recording starts, but I cant do anything with the Gui it is like freeezed, a Console still appeares and i can only stop the process by pressing a key in the console.
Here is a snippit of the Console Code:
class BHJKL
{
system
private static A;
private static B;
// This method will be executed every time new data is received
static void OnNewDataReceived(object sender, NewDataEventArgs eventArgs)
{
//some code in here
using (StreamWriter file = new StreamWriter(#"C:\Users\XYZ\File_Trial" + DateTime.Now.DayOfYear + ".csv", true))
{
//Writeline data..
}
}
}
// This was the Main Method before i changed it
public static void Record()
{
// Here is some Code that configure the Settings of the device
// initialize device
// MORE CODE USING THE COMPANYS EXTERN LIBRARYS TO START THE DEVICE
//start device
deviceManager.DeviceStart();
while (!Console.KeyAvailable) // as long as no key is pressed do...
{
Thread.Sleep(100); // do nothing, let the event processing thread that is managed by the library handle incomming data
}
//stop device
deviceManager.DeviceStop();
//unsubscribe event
deviceManager.NewDataReceived -= OnNewDataReceived;
//deinitialize device
deviceManager.DeinitializeDevice();
//dispose device
deviceManager.Dispose();
}
}
My Attempt:
Changing the main method into static Recording.
Than by Pressing the Start Button, call the method.
Write this at the end of the method:
while (Rec==true)
{
Thread.Sleep(100);
}
By Pressing the Stop Button: set.Rec(false)
But after Pressing the start Button, i cant press the stop button anyome.
I hope someone can understand my Problem and can give me some advices.
Thread.Sleep blocks your UI from doing anything. Consider using a System.Windows.Forms.Timer
Rather than sleeping in a loop, you should just let your Start method return. Move all of the code that comes after the sleep loop into your Stop button's click event handler.
(Depending on how the code is structured, you may also have to switch deviceManager from being a local variable to being a field in the class)
Related
I'm making a quiz game and want to make sure that the user does not get additional answering time by exiting the app (without shutting it down).
My current timer uses Time.deltaTime. I'm thinking of replacing this with something like DateTimeOffset.Now.ToUnixTimeMilliseconds() (epoch time) or Time.realtimeSinceStartup (not sure if this one works). A solution to detect when the user closes the app would also work.
There are three built-in functions that might do what you want. There is OnApplication.Quit (does not work on mobile), OnApplication.Pause, and OnApplicationFocus.
I personally like using OnApplicationPause instead of OnApplicationFocus as focus is called on some phones when the keyboard is brought up. I have found that pause is called whenever a user hits the home button, closes the app, their phone dies, turns off their phone, etc.
The great part about the OnApplicationFocus and OnApplicationPause is that there is a bool parameter passed in to let you know whether you are unfocused or focused / unpaused or paused.
If you just want to know how long it has been since the last time the app is opened, you can easily stored a variable locally after an OnApplicationPause is called when the bool is true, then when it is false, you can detect how much time has elapsed. As the local variable will not persist if the user quits the game, you will need to also look into some sort of save/load implementation. There are already many good answers on StackOverflow for how to save data in Unity, so if you need help with that I can add a link.
As for the OnPause example here is how I would use it.
private long lastTimePaused = 0;
private void Awake
{
// setting our paused time to the start time
lastTimePaused = DateTimeOffset.Now.ToUnixTimeMilliseconds();
}
void OnApplicationPause(bool pauseStatus)
{
if(pauseStatus)
{
lastTimePaused = DateTimeOffset.Now.ToUnixTimeMilliseconds();
// save this lastTimePaused if you want the data to persist between a user quitting the app
// and coming back
}
else
{
Debug.Log("Our elapsed miliseconds is: " + (DateTimeOffset.Now.ToUnixTimeMilliseconds() - lastTimePaused));
}
}
If you like, you can also use OnApplicationFocus together with OnApplicationPause. Something like:
private long lastTimePaused = 0;
private void Awake
{
// setting our paused time to the start time
lastTimePaused = DateTimeOffset.Now.ToUnixTimeMilliseconds();
}
void OnApplicationPause(bool pauseStatus)
{
HandlePause(pauseStatus);
}
void OnApplicationFocus(bool hasFocus)
{
HandlePause(!hasFocus);
}
private void HandlePause(bool isPaused)
{
if(isPaused)
{
lastTimePaused = DateTimeOffset.Now.ToUnixTimeMilliseconds();
// save this lastTimePaused if you want the data to persist between a user quitting the app
// and coming back
}
else
{
Debug.Log("Our elapsed miliseconds is: " + (DateTimeOffset.Now.ToUnixTimeMilliseconds() - lastTimePaused));
}
}
I am not sure what cases you would like to detect when a user is suspended, but first, try OnApplicationPause to see if it handles everything you need. If it does not, you can also combine it with OnApplicationFocus.
I've implememted a small Console Application that checks how long a programm is running. I then tried to run the application and everything is working fine. However then i hit (by accident) the "pause" key on my Keyboard and the programm stopped executing.
Is there a way to handle this event in a Console Application to suppress this pausing?
Update:
class Program
{
static void Main(string[] args)
{
while (true)
{
Thread.Sleep(2000);
var p = Process.GetProcessesByName("wineks");
if (p != null)
{
Console.WriteLine("Found Process. Close it please");
Console.ReadKey();
}
}
}
}
That is basically my code. It is only asking the user to close a specific process. If I know hit the Pause Button on my Keyboard before I see the message, the message will never appear because the application freezes and seems like paused.
From browsing in the Internet I know that the key I press has the Name Pause and the key is sending some kind of Event or Signal to the Console.
Actually the Console does not have a way to raise KeyPress events , you can however try some looped approach to handle any key press done accidentally . Refer to this stackoverflow question here
Try inserting these lines before GetProcessByName
if (Console.KeyAvailable)
{
if (ConsoleKey.Pause == Console.ReadKey().Key)
continue;
}
I'm starting out in C#, coded a lot in Java but having some trouble here. I'm trying to learn how to use MouseKeyHook for an application I'm developing. I cannot get the actual listener to fire off an event. Here's my listener code:
using System;
using System.Windows.Forms;
using Gma.System.MouseKeyHook;
namespace ChromaHeatmap
{
class keyListener
{
private IKeyboardMouseEvents m_GlobalHook;
public void Subscribe()
{
// Note: for the application hook, use the Hook.AppEvents() instead
m_GlobalHook = Hook.GlobalEvents();
m_GlobalHook.KeyPress += GlobalHookKeyPress;
}
private void GlobalHookKeyPress(object sender, KeyPressEventArgs e)
{
Console.WriteLine("blah");
}
public void Unsubscribe()
{
m_GlobalHook.KeyPress -= GlobalHookKeyPress;
//It is recommened to dispose it
m_GlobalHook.Dispose();
}
}
}
And here's the part of my application code where I attempt to do something with the listener. If anyone can let me know what the best way is to loop here and wait for events, I'd appreciate it.
//Listen for key presses
keyListener heyListen = new keyListener();
heyListen.Subscribe();
while(true)
{
}
while(true) {}
This is a hold-and-catch-fire statement, the thread will burn 100% core and cannot execute the hook callback. You'll notice that the machine goes dead for 5 seconds when you press a key, the operating system is waiting for an opportunity to invoke the callback. But it won't wait forever and unceremoniously will destroy the hook so you regain control over the machine. Also the kind of mishap that will occur when you try to debug your event handler.
Windows needs an opportunity to safely call the hook callback. That requires your program to be "idle", not executing any code. The technical term for this is "pumping the message loop", your program must wait for a notification from the operating system that something interesting happened.
A very simple way is to use the Winforms project template as-is, you'll also get a window. Note how the Main() method in the project makes the call that you need instead of the while() loop. You must call Application.Run().
Check this post for code that avoids displaying a window.
I am currently implementing my final year project as a Music Software Development student.
I am making a software that plays a midi track that is generated earlier in the process.
In my interface, there is a button "play" and a button "stop".
When I click "play", a loop is called that plays this track. In this loop, I call a function from an instance of an other class.
What I would like is that when the user press "pause", the loop is temporary stopped, and when he press "pause" again, it goes back exactly where it was in the loop.
So far, when I press play, the track plays exactly how I want to, but I can't use any other element of my window until the loop is not completly processed.
Here is my code.
private void playStopButton_Click(object sender, RoutedEventArgs e)
{
// Initialising my output midi devices
outDevice.Send(new ChannelMessage(ChannelCommand.ProgramChange, information.bassChannel, information.bassSound));//bass
outDevice.Send(new ChannelMessage(ChannelCommand.ProgramChange, information.guitarChannel, information.guitarSound));//guitar
for (int barNum = 0; barNum < Globals.numberOfBars; barNum++)
{
// playing the first beat
rythmicPattern.play(0, ref outDevice, information, Globals.chordProgression.Bars[barNum].Chord);
//second beat
rythmicPattern.play(1, ref outDevice, information, Globals.chordProgression.Bars[barNum].Chord);
//thrid beat
rythmicPattern.play(2, ref outDevice, information, Globals.chordProgression.Bars[barNum].Chord);
//fourth beat
rythmicPattern.play(3, ref outDevice, information, Globals.chordProgression.Bars[barNum].Chord);
}
}
private void playPauseButton_Click(object sender, RoutedEventArgs e)
{
// test if the track is being played
if (isPlaying)
rythmicPattern.Pause();
else
// if it was already paused, playing back from where I stopped
rythmicPattern.PlayAfterPause(beatNumber);
}
Thank you for your help.
Greg
You must use threading where you can play the sound in another thread, so you can execute pause method
Check this link Multi-threading in .NET: Introduction and suggestions
We have a little C# startup appplication that users launch to run the latest version of our main C# WinForms application from a network share. It's kind of a simplified ClickOnce arrangement (our IT folks won't allow us to use ClickOnce).
The startup application exits after calling Process.Start("MainApplication.exe"), but the main application can take several seconds to display, leaving the user with a blank screen.
Is there a way that the starup application can poll the OS to find out if the main aplication is running before it exits? Or some other way to handle this?
You can use Process.WaitForInputIdle() to wait until your application enteres the Idle state.
Process appProcess = Process.Start("MainApplication.exe");
appProcess.WaitForInputIdle();
From MSDN:
...you have just started a process and
want to use its main window handle,
consider using the WaitForInputIdle
method to allow the process to finish
starting, ensuring that the main
window handle has been created
Remarks Section from Process.MainWindowHandle property.
You can call Process.GetProcessByName to see if the new process has been created. The other option would be to have your main application kill the startup application once it has finished loading.
Use Davids' suggestion or alternatively you can put a splash screen in your main application. It will be just a simple Form with an image running on a separate worker thread. Put this as the first item invoked on start up. Your app can continue initializing on the main thread & after some seconds or just before your Main app finishes initialization kill the worker thread.
One way to solve this easily is to use a global event to signal the startup application that the main app has reached a predetermined state. To do this create a named event handle in the startup application and wait for it to be signaled:
static void Main(string[] args)
{
const string globalName = "MyProgramName";//something unique
bool isNew = false;
ManualResetEvent mreExited = new ManualResetEvent(false);
EventWaitHandle mreStarted = new EventWaitHandle(false, EventResetMode.ManualReset, globalName, out isNew);
try
{
if (!isNew)//already running, just exit?
return;
//start and monitor for exit
Process pstarted = Process.Start("...");
pstarted.Exited += delegate(object o, EventArgs e) { mreExited.Set(); };
pstarted.EnableRaisingEvents = true;
int index = WaitHandle.WaitAny(new WaitHandle[] { mreExited, mreStarted });
if (index == 0)//mreExited signaled
throw new ApplicationException("Failed to start application.");
}
finally
{
mreExited.Close();
mreStarted.Close();
}
}
Then in the main program you signal the event once your ready for the startup application to quit:
static void Main(string[] args)
{
const string globalName = "MyProgramName";//same unique name
bool isNew = false;
EventWaitHandle mreStarted = new EventWaitHandle(false, EventResetMode.ManualReset, globalName, out isNew);
try
{
if (!isNew)
mreStarted.Set();
Application.Run(new Form());
}
finally
{
mreStarted.Close();
}
}
I think David's second option is the way to go here. The process may be running with no visible UI yet. So, once the main form is displayed in the second app, kill the first process. You could even, conceivably, pass the process id of the original process in via StartInfo when you start the new process.
There are many trade-offs involved in this, but you may be able to make start-up time fast enough to make this issue moot by using NGEN.
My suggestion is to put Splash Screen in your application it gives you a good feel rather than if you dont want to use Splash screen then kill the process when loading is finished. Or you can use Process.GetProcessByName()
For Splash Screen just make a Window Screen and in startup class just inherit the class from Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase that gives you a method OnCreateSplashScreen() Override this method like this :-
protected override void OnCreateSplashScreen()
{
base.OnCreateSplashScreen();
//yourSplashScreen is the screen you made as a window form either it would be a image or form
SplashScreen = yourSplashScreen();
}
Thanks ...Saurabh Singh Happy To Code