In my XNA game, I've got the game window and the console which is running a threaded Console.ReadLine() so the game doesn't hang while waiting for scripting input. I'm trying to get it where when the game window closes, the Console closes automatically, as well as the input to actually work (with the ability to print things out whilst waiting on input).
I've gotten it to close automatically now by using code from this question: How to add a Timeout to Console.ReadLine()?
However, when I press enter to the input, an ObjectDisposedException is thrown. Also, I'm stuck with using a timeout when I'd rather the thing be instant. How would I go about fixing this?
public class ConsoleInput
{
public bool running = true;
public void Run()
{
String input;
while (running)
{
input = ReadLine(500);
//stuff
}
}
string ReadLine(int timeoutms)
{
ReadLineDelegate d = Console.ReadLine;
IAsyncResult result = d.BeginInvoke(null, null);
result.AsyncWaitHandle.WaitOne(timeoutms);//timeout e.g. 15000 for 15 secs
if (result.IsCompleted)
{
string resultstr = d.EndInvoke(result);
Console.WriteLine("Read: " + resultstr);
return resultstr;
}
result.AsyncWaitHandle.Dispose();
return "";
}
delegate string ReadLineDelegate();
}
Which is called by:
LuaInput = new ConsoleInput();
LuaInputThread = new Thread(new ThreadStart(LuaInput.Run));
LuaInputThread.Start();
Thanks!
Have you tried setting the thread's
IsBackground = true; ? This will force it closed and will not allow the thread to block.
Related
We have a windows service which runs a while loop and monitor the database for pending orders. It works fine however latly we notice that in high load environment its opening two threads to process instead of one.
In this code, when StartService() is called, it opens a new thread and process orders in DB. This code should always call start service only once however why do we see multiple threads open ? Do you see any bug with this design ?
Here Queue.IsFull is a Volatile Bool flag.
public static void StartWork()
{
bool started = false;
//Infinite Loop
while (continueWork)
{
try
{
//Bool flag to prevent back to back call
if (started == false)
{
started = true;
// Do work only if Any Pending Request in Database.
if (AppSettings.AnythingToPRocess() == true)
{
if (Queue.IsFull == false)
{
StartService(); //set Queue.IsFull to True inside
}
}
started = false;
}
}
catch (Exception exp)
{
LogError("Failed to Start" , exp);
}
finally
{
System.Threading.Thread.Sleep(5000); //5 seconds
}
}
}
private static void StartService()
{
// Set Flag to false here to prevent back to back calls
Queue.IsFull = true;
Log("Service started");
Thread ServiceThread = new Thread(() =>
{
Service service = new Service();
service.Process();
});
ServiceThread.Name = "Thread1";
ServiceThread.Start();
}
Sleep(5) is not 5 seconds, it's milliseconds.
Unless there's an exception, started will always end up false so if StartService is asynchronous then the try block will run again.
As I can understand from your post, you are starting the service and it runs in a different thread. In that case the started flag should be set as false by exiting the service.
I came across an issue, and I'm not sure if it's me or if there's an issue with thread locking.
I have a class I use for basic utilities. In that class is method to create or append a text file. And because I use it debug, I have the method using lock() to keep the access singular. Except, it appears to be failing and allowing multiple threads into the blocked code.
When running my test threads it doesn't throw an error every time. It's a little weird. There are 50 threads/tasks being created. Each thread is writing a line to a singe file using the class below. It cycles through about 3100 individual tasks. But a maximum of 50 tasks are created to handle each batch. As each thread completes its task, a new one is created to take its place. The last batch processed 3188 commands and threw 16 errors.
I have tried using Monitor.Enter and Exit, but I get the same results. I have also tried making the StdLibLockObj readonly. All with the same results.
Error: The process cannot access the file 'ThreadExe.txt' because it is being used by another process.
static class StdLib
{
private static object StdLibLockObj = new object();
public static void WriteLogFile(string #AFileName, string FileData, bool AppendIfExists = true, bool AddAppPath = true)
{
lock (StdLibLockObj)
{
StreamWriter sw = null;
try
{
if (AddAppPath)
{
AFileName = #Path.Combine(#ApplicationPath(), #AFileName);
}
if ((AppendIfExists) && File.Exists(AFileName))
{
sw = File.AppendText(AFileName);
}
else
{
sw = File.CreateText(AFileName);
}
sw.Write(FileData);
}
finally
{
if (sw != null)
{
sw.Flush();
sw.Close();
sw.Dispose();
}
sw = null;
}
}
}
}
My background is mostly in Delphi, where threading is a bit more granular.
Any help would be appreciated.
Wrap your StreamWriter entries in a "using" block. That will get rid of locking. Sort of like this:
public static void ErrorMessage(string logMessage)
{
using (StreamWriter sw_errors = new StreamWriter(m_errors, true))
{
sw_errors.Write("\r\nLog Entry : ");
sw_errors.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
DateTime.Now.ToLongDateString());
sw_errors.WriteLine(" :");
sw_errors.WriteLine(" :{0}", logMessage);
sw_errors.WriteLine("-------------------------------");
}
}
I'm using sox.exe to play some audio files.
This is how I'm calling it:
SoxPlayer = new Process
{
StartInfo = new ProcessStartInfo
{
CreateNoWindow = true,
RedirectStandardError = true,
UseShellExecute = false,
FileName = Play,
Arguments = arg,
WorkingDirectory = Application.StartupPath + "\\bin\\"
}
};
and this is the code that should be interpreting the StandardError output:
private void UpdatePlaybackTime(string output)
{
if (string.IsNullOrEmpty(output)) return;
if (!output.Contains("%") || !output.Contains("[")) return;
var index1 = output.IndexOf("%", StringComparison.Ordinal) + 1;
var index2 = output.IndexOf("[", StringComparison.Ordinal);
var time = output.Substring(index1, index2 - index1).Trim();
var times = time.Split(new[] { ":" }, StringSplitOptions.None);
var seconds = Convert.ToDouble(times[0]) * 3600;
seconds = seconds + (Convert.ToDouble(times[1]) * 60);
seconds = seconds + (Convert.ToDouble(times[2]));
if (seconds == 0 || seconds < PlaybackSeconds) return;
PlaybackSeconds = seconds;
}
My goal is to get the playback time from the sox output as accurately as possible, rather than work (as I was doing before) with an internal timer that may lose sync with sox's own.
My first attempt was using this recommendation I found online:
SoxPlayer.ErrorDataReceived += (sender, args) => UpdatePlaybackTime(args.Data);
SoxPlayer.Start();
SoxPlayer.BeginErrorReadLine();
This current code "works" in that I get the information I want, but it seems like UpdatePlaybackTime() is being called every 5 seconds or so. When it's called, the info obtained is accurate, but obviously I want to update the playback info several times per second, not every 5 seconds.
My understanding is that what is happening is that UpdatePlaybackTime is being called when the StandardError buffer gets full. I've tried calling SoxPlayer.BeginErrorReadLine() with my player timer but it says it's already running asynchronously. I've tried SoxPlayer.StandardError.DiscardBufferedData() but it throws an exception because of the asynchronous process that is ongoing.
So, how can I manage to capture the playback information how I need? Thank you in advance!
EDIT:
After discussing this code and how it's not working because of buffering, I've also tried the following inside a separate BackgroundWorker thread, with the same result (i.e. updates only about every 5 seconds):
SoxPlayer.Start();
SoxTimer.RunWorkerAsync();
private void SoxTimer_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
var sr = new StreamReader(SoxPlayer.StandardError.BaseStream);
while (sr.Peek() > 0)
{
var line = sr.ReadLine();
UpdatePlaybackTime(line);
}
}
private void SoxTimer_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
if (!SoxPlayer.HasExited)
{
SoxTimer.RunWorkerAsync();
}
}
When this BackgroundWorker completes, it checks if SoxPlayer.HasExited, and if it hasn't, it runs again. This has the same effect as my first attempt. PlaybackSeconds is only getting updated about every 5 seconds, at which point it updates to the right time, and then the rest of the code that acts based on the PlaybackSeconds value works as well.
I also tried achieving the same by creating a Thread to work the reading of the StandardError output. Every instance results in the same, a 5 second or so delay between when UpdatePlaybackTime() gets called. When it does, it iterates through all the output that was sent to StandardError since the last time we iterated through it, so it then updates the PlaybackSeconds value very quickly in small increments and leaves it at the current value at that time. But again, one update as far as the user is concerned every 5 seconds.
Sox creators are adamant that the problem is not on their end. When played in a console window, output is constant. According to sox creators, every 0.1 seconds. If I tell sox to output is standarderror to a text file, the same happens. There's a constant updating of the information on the text file. Yet reading the StandardError stream itself, I have now spent the better part of two days with no acceptable results.
Thank you for your help.
EDIT 2:
Following Peter's advice below, here's a brand new project. Didn't even change the default names for anything. Same behavior as described so far. So I'm going back to blame (ahem, discuss with) the SoX peeps.
using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private Process SoxPlayer;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var bin = Application.StartupPath + "\\bin\\";
SoxPlayer = new Process
{
StartInfo = new ProcessStartInfo
{
CreateNoWindow = true,
RedirectStandardError = true,
UseShellExecute = false,
FileName = bin + "sox.exe",
Arguments = "song.ogg -c 2 -d",
WorkingDirectory = bin
}
};
SoxPlayer.Start();
var thread = new Thread(() =>
{
int cch;
var rgch = new char[1];
while ((cch = SoxPlayer.StandardError.Read(rgch, 0, rgch.Length)) > 0)
{
var cch1 = cch;
label1.Invoke(new MethodInvoker(() => label1.Text = new string(rgch, 0, cch1)));
}
});
thread.Start();
}
private void button2_Click(object sender, EventArgs e)
{
SoxPlayer.Kill();
}
}
}
Here is a simple code example that does not reproduce the behavior you describe:
class Program
{
static void Main(string[] args)
{
Process process = new Process();
process.StartInfo.FileName = "SimpleStderrWriter.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
process.Start();
Thread thread = new Thread(() =>
{
int cch;
char[] rgch = new char[1];
Console.WriteLine("Reading stderr from process");
while ((cch = process.StandardError.Read(rgch, 0, rgch.Length)) > 0)
{
Console.Write(new string(rgch, 0, cch));
}
Console.WriteLine();
Console.WriteLine("Process exited");
});
Console.WriteLine("Press Enter to terminate process");
thread.Start();
Console.ReadLine();
process.StandardInput.WriteLine();
thread.Join();
}
}
Here is the code for the SimpleStderrWriter.exe program:
class Program
{
static void Main(string[] args)
{
bool exit = false;
Thread thread = new Thread(() =>
{
while (!Volatile.Read(ref exit))
{
Console.Error.Write('.');
Thread.Sleep(250);
}
});
thread.Start();
Console.ReadLine();
Volatile.Write(ref exit, true);
thread.Join();
}
}
This code example demonstrates clearly, by receiving and re-emitting the child process's stderr output as quickly as it's generated, that there is nothing in .NET that by default would cause the delay you are experiencing. The obvious conclusion is that either your advisors with respect to SoX are wrong and it does some buffering for some reason, or that you yourself have added something to your code that introduces the delay you are experiencing.
If you are positive the latter is not the case, then you need to go back to your SoX advisor and explain to them that they are mistaken. If you are positive that the SoX advisor is correct, then you need to post an example similar to the above, but which does reproduce the delay you are experiencing.
I've a got a problem with the infamous message "The thread xxx has exited with code 0 (0x0)".
In my code I have a main class called "Load" that starts with a Windows Form load event:
public class Load
{
public Load()
{
Device[] devices = GetDevices(); // Get an array of devices from an external source
for (int i = 0; i < devices.Length; i++)
{
DeviceDiagnosticCtrl deviceDiagnostic = new DeviceDiagnosticCtrl(devices[i].name);
}
}
}
Inside the constructor, for each generic device read from an external source, I initialize a custom diagnostic class that runs a thread:
public class DeviceDiagnosticCtrl
{
private Thread diagnosticController;
private volatile bool diagnosticControllerIsRunning = false;
public DeviceDiagnosticCtrl(string _name)
{
// Thread initialization
this.diagnosticController = new Thread(new ThreadStart(this.CheckDiagnostic));
this.diagnosticController.Start();
this.diagnosticControllerIsRunning = true;
}
private void CheckDiagnostic()
{
while (this.diagnosticControllerIsRunning)
{
try
{
// Custom 'Poll' message class used to request diagnostic to specific device
Poll poll = new Poll();
// Generic Message result to diagnostic request
IGenericMessage genericResult;
// Use a custom driver to send diagnostic request
SendSyncMsgResult res = this.customDriver.SendSyncMessage(poll, out genericResult);
switch (res)
{
case SendSyncMessageResult.GOOD:
{
// Log result
}
break;
case SendSyncMessageResult.EXCEPTION:
{
// Log result
}
break;
}
Thread.Sleep(this.customDriver.PollScantime);
}
catch (Exception ex)
{
// Loggo exception
}
}
}
}
When I run the above code in debug mode I always read 8 devices from external source, and for each of them I continuously run a managed thread to retrieve diagnostic.
My problem is that randomly one or more of the 8 threads I expect from the code above exit with code 0, without any exception.
I've started/restarted the code in debug mode a lot of time, and almost everytime one of the thread exits.
I've read somewhere (i.e. this SO question) that it could depends of Garbage Collector action, but I'm not too sure if this is my case - and how to prevent it.
Do someone see something strange/wrong in the sample code I posted above? Any suggestion?
'while (this.diagnosticControllerIsRunning)' is quite likely to fail immediate, in which case the thread drops out. It's no good starting the thread and THEN setting 'this.diagnosticControllerIsRunning = true;' - you're quite likely to be too late.
Bolt/stable-door. Something like:
do{
lengthyStuff with Sleep() in it
}
while (this.diagnosticControllerRun);
Copied from Here
Right click in the Output window when you're running your program and
uncheck all of the messages you don't want to see (like Thread Exit
messages).
maybe it is a bad question, but I have a Client App which sends some Commands to the server. I made a little function for sending commands, which simply waits until a message is received over AutoResetEvent.WaitOne() and then returns the message as string. I used this function very often in my client app, because it was a fast way to implement sth.
Now I want to show a LoadingCircle in this app while it is waiting from the response from the Server. I already wrote sth for that in the message receiving function, which simply adds the control to the Form. This is working find, but UserControl(Loading Circle), which redraws after some milliseconds, doesnt redraw anymore, because AutoResetEvent.WaitOne() is blocking the GUI Thread. I know that I could move the message receiving part into another Thread, but I dont want to change the concept of this function, because I used the message receiving function over 150x.
So my question is: Is there a lazy way to do that, so that It does GUI Events while its waiting, or maybe I can move the drawing part of the LoadingCircle Control into another Thread?
Any help will be greatly appreciated
You have essentially taken an async operation and turned it into a synchronous operation via AutoResetEvent.WaitOne. And now you want to turn it back into an async operation.
My suggestion would be to separate the function from the UI. Then tool a synchronous and an async option. That way you get to keep a fully functioning app and can incrementally release during your code re-write of the 150 instances that need changed.
The new async and await keywords in 4.5 should serve you well here.
I found a small fix for that here, which works well(I cant take credit for it)
private static TimeSpan InfiniteTimeout = TimeSpan.FromMilliseconds(-1);
private const Int32 MAX_WAIT = 100;
public static bool Wait(WaitHandle handle, TimeSpan timeout)
{
Int32 expireTicks;
bool signaled;
Int32 waitTime;
bool exitLoop;
// guard the inputs
if (handle == null) {
throw new ArgumentNullException("handle");
}
else if ((handle.SafeWaitHandle.IsClosed)) {
throw new ArgumentException("closed wait handle", "handle");
}
else if ((handle.SafeWaitHandle.IsInvalid)) {
throw new ArgumentException("invalid wait handle", "handle");
}
else if ((timeout < InfiniteTimeout)) {
throw new ArgumentException("invalid timeout <-1", "timeout");
}
// wait for the signal
expireTicks = (int)Environment.TickCount + timeout.TotalMilliseconds;
do {
if (timeout.Equals(InfiniteTimeout)) {
waitTime = MAX_WAIT;
}
else {
waitTime = (expireTicks - Environment.TickCount);
if (waitTime <= 0) {
exitLoop = true;
waitTime = 0;
}
else if (waitTime > MAX_WAIT) {
waitTime = MAX_WAIT;
}
}
if ((handle.SafeWaitHandle.IsClosed)) {
exitLoop = true;
}
else if (handle.WaitOne(waitTime, false)) {
exitLoop = true;
signaled = true;
}
else {
if (Application.MessageLoop) {
Application.DoEvents();
}
else {
Thread.Sleep(1);
}
}
}
while (!exitLoop);
return signaled;
}