I'm trying to use a thread multiple times and have the thread stop processing if the user doesn't react fast enough.
Thread ask = new Thread (new ThreadStart (MathQuiz.prompt));
ask.Start();
ask.Join(30000);
if (answer == 4)
{
score = score+1;
answer = 0;
}
Console.WriteLine();
Console.WriteLine("Press any key to move on to the next question!");
Console.WriteLine();
Console.ReadKey(true);
Console.WriteLine("What is 15 / 3?");
Console.WriteLine();
ask.Start();
ask.Join(30000);
if (answer == 5)
{
score = score+1;
answer = 0;
}
...
static void prompt()
{
preanswer = (Console.ReadLine());
if (!decimal.TryParse(preanswer, out answer))
{
Console.WriteLine("That wasn't even a number or decimal!");
}
else
{
answer = decimal.Parse(preanswer);
}
}
Right now it doesn't seem that the "prompt" thread is terminating, and so it crashes when the second question begins.
So I need a solution! I of course don't mind to answer questions to help myself get an answer.
The method Thread.Join(Int32) doesn't stop the other thread after the given number of milliseconds. It just stops waiting. It returns true if the other thread has terminated.
So if ask.Join(30000); returns false, the other thread is still running and you have to Abort the thread yourself.
What evidence do you have that the prompt thread is not terminating? The main thread should be waiting for the prompt thread to terminate at the "join" places, so, if execution continues past a join, the "prompt" thread terminated.
Take a look at the example on MSDN's Thread.Join() page. The example uses two different methods for passing work to a thread. regularThread is what you are trying to do. For the simple task in your example, I think doing a join() without events or locks is a reasonable solution. If you are prototyping to make a product that is much more robust than your example implies, then you should also: 1) read up on the ThreadPool . It avoids the cost of creating/disposing threads. 2) Put a lock() block around reads and writes to the answer variable.
A word of warning: Other answers mention using Thread.Abort(). Calling Thread.Abort() on the currently executing thread is fine and nearly equivalent of throwing an exception. However calling Thread.Abort() on a different thread should be avoided. There's several scenarios where it can result in the thread not cleaning up properly.
Console.ReadLine blocks the current thread from being aborted until the line has been read. (As per comment from Timwi)
To work around this, you would have to use the Console.KeyAvailable method here: How to add a Timeout to Console.ReadLine()?
I re-wrote the problem before realising my mistake, and now here's a solution.
It's rather more involved than I wanted it to be. (Using the KeyAvailable means I need to queue up the keys entered, and to support backspace I have to remove the items. I also need to sleep while no keys are available... )
private static AutoResetEvent answered = new AutoResetEvent(false);
private static Func<string, bool> questionCorrect = null;
private static bool? correct;
static void Main(string[] args)
{
int score = 0;
AskQuestion(ref score,
"What is 15 / 3?",
TimeSpan.FromSeconds(5),
answer =>
{
decimal value;
if (!decimal.TryParse(answer, out value))
{
Console.WriteLine(
"That was not a valid number");
return false;
}
return (value == 15/3);
});
AskQuestion(ref score,
"What is 20 * 2 ?",
TimeSpan.FromSeconds(5),
answer =>
{
decimal value;
if (
!decimal.TryParse(answer,
out value))
{
Console.WriteLine(
"That was not a valid number");
return false;
}
return (value == 20*2);
});
Console.WriteLine("Done. Score: {0}", score);
Console.ReadLine();
}
private static void AskQuestion(ref int score, string question, TimeSpan duration, Func<string, bool> validator)
{
// Setup
questionCorrect = validator;
correct = null;
answered.Reset();
// Ask
Console.WriteLine(question);
Thread thread = new Thread(GetQuestion);
thread.Start();
// Wait
answered.WaitOne(duration);
thread.Abort();
thread.Join();
Console.WriteLine(); // Write empty line, otherwise this overwrites the answer.
// Validate);
if (correct.HasValue && correct.Value == true)
{
score++;
Console.WriteLine("Correct");
}
else if (correct.HasValue)
{
Console.WriteLine("Incorrect");
}
else
{
Console.WriteLine("Timeout");
}
}
private static void GetQuestion()
{
try
{
List<char> captured = new List<char>();
bool answerCaptured = false;
while (!answerCaptured)
{
while (Console.KeyAvailable)
{
var key = Console.ReadKey();
if (key.KeyChar == '\r' || key.KeyChar == '\n')
{
answerCaptured = true;
break;
}
if (key.KeyChar == '\b' && captured.Count > 0)
{
captured.RemoveAt(captured.Count - 1);
}
else
{
captured.Add(key.KeyChar);
}
}
Thread.Sleep(50);
}
string answer = new string(captured.ToArray());
correct = questionCorrect.Invoke(answer);
answered.Set();
}
catch (ThreadAbortException)
{
// will be thrown when the thread times out.
}
}
Related
I have two threads reaching a point in the server program at slightly differing times, both sending a string. I want the server to pause at this point until both threads have received a string and then continue. Currently I am using Console.ReadKey(); in order to "pause" the thread. But this isn't a solution as I need to press a key twice (one for each thread) in order to progress.
Is there a possibility of having a global counter in the program class which is accessible and editable by all threads at all times? A similiar concept to a ConcurrentDictionary. That way I can distinguish between threads based on which thread sent a string first and make the program hang until the counter is satisfied that both clients have 'answered'.
class Program
{
public static bool isFirstThread = false;
static void Main(string[] args)
{
runServer();
}
static void runServer()
{
//server setup
Thread[] threadsArray = new Thread[2];
int i = 0;
try
{
while(true) //game loop
{
Socket connection;
connection = listener.AcceptSocket();
threadRequest = new Handler();
if(i==0) //first thread
{
threadsArray[i] = new Thread(() => threadRequest.clientInteraction(connection, true);
}
else //not first thread
{
threadsArray[i] = new Thread(() => threadRequest.clientInteraction(connection, false);
}
threadsArray[i].Start();
i++;
}
}
catch(Exception e)
{
Console.WriteLine("Exception: " + e.ToString());
}
}
}
class Handler
{
public void clientInteraction(Socket connection, bool isFirstThread)
{
string pAnswer = string.Empty;
//setup streamReaders and streamWriters
while(true) //infinite game loop
{
//read in a question and send to both threads.
pAnswer = sr.ReadLine();
Console.WriteLine(pAnswer);
Console.ReadKey(); //This is where I need the program to hang
awardPoints();
}
}
}
This is a rough idea of what my code is doing, I've chopped quite a bit to avoid question bloat so there might be a couple of things that are in error that I've missed.
I could in theory just set a timer from when the question string is sent from the server, but I would rather not at this stage.
Any thoughts or pointers would be much appreciated. Thanks in advance.
Use a System.Threading.Barrier, which is designed for this exact purpose: making each thread in a group of threads wait until all of them have reached some point in their computation. Initialize it in runServer() like this:
Barrier barrier = new Barrier(2);
And do this at the end of each thread:
barrier.SignalAndWait();
I'm trying to create a C# .net 4.5 console application that will run a loop continuously unless passed a command from the user. I don't want to check for an input from the user each time the loop completes because I expect this to run at least hours without user input, maybe even longer, however they should be able to type a command into the console at any time to be evaluated for how the loop should behave.
To allow for user input at the same time the loop is running I believe I need to use threading such as async-await, however I'm quite new to programming and I'm not sure if threading is even the right approach. I've also recently learned of Services and since the user input is mostly stop and start, this may be the better approach.
How should I modify my code below to implement asynchronous functionality allowing user input while running a continuous loop? Should this be a service instead as most user input is start and stop?
I've included the code I've written so far:
class Program
{
static void Main(string[] args)
{
OptionMenu();
Console.ReadLine();
}
static void OptionMenu()
{
string command = "";
Console.WriteLine("Please enter a command: \n");
while (command != "exit")
{
command = Console.ReadLine().ToLower();
switch (command)
{
case "exit":
command = "exit";
break;
case "pause":
command = "Pause";
break;
case "start":
while (command != "Pause")
{
PrimaryWork();
}
break;
default:
Console.WriteLine("I'm sorry Dave, I'm afraid I can't do that");
break;
}
}
}
static void PrimaryWork()
{
Console.WriteLine("Results of PrimaryWork should be written to a repository");
Thread.Sleep(5000);
}
}
Here's a pattern that might help you:
void Main()
{
var tokenSource = new CancellationTokenSource();
var t=new Thread(_ => DoWork(tokenSource.Token));
for(;;) //loop forever
{
var input = Console.ReadLine();
if(input == "exit")
{
tokenSource.Cancel();
break;
}
}
}
void DoWork(CancellationToken token)
{
for(;;)
{
//do some work
if(token.IsCancellationRequested)
{
break;
}
}
}
It is unlikely using async/await will make your code easier in this case.
Consider creating separate thread that deals with "primary work" and have main thread posting command to ConcurrentQueue which will be checked by the other thread.
Starting point Thread.Start:
var commands = new ConcurrentQueue<string>();
var myThread = new Thread(_ =>
{
while(true)
{
// Do work
...
// check commands
string command;
if (commands.TryDequeue(out command))
{
//handle command
}
}
});
myThread.Start();
commands.Enqueue(Console.ReadLine());
I'm trying to start one thread, receive string from it and then start n-counts of threads with the received string. Code:
private void button2_Click(object sender, EventArgs e)
{
string post = null;
sync = new ManualResetEvent(false);
var thr = new Thread[1];
thr[0] = new Thread(delegate() { post = create_note(); });
thr[0].IsBackground = true;
thr[0].Start();
sync.WaitOne();
decimal value = Program.Data.numericUpDown1;
int i = 0;
int j = (int)(value);
thr = new Thread[j];
for (; i < j; i++)
{
thr[i] = new Thread(() => invite(post));
thr[i].IsBackground = true;
thr[i].Start();
}
}
public string create_note()
{
while (true)
{
string acc = "";
string proxy = "";
if (Program.Data.checkBox1 || Program.Data.checkBox2)
{
if (Program.Data.checkBox1)
Proxy.type = "http";
else if (Program.Data.checkBox2)
Proxy.type = "socks5";
lock (locker)
{
if (Proxy.proxies.Count == 0)
{
foreach (string prox in File.ReadAllLines(proxy_path))
{
if (prox.Contains(":"))
Proxy.proxies.Add(prox);
}
}
}
proxy = rand_proxy();
}
else if (!Program.Data.checkBox1 && !Program.Data.checkBox2)
Proxy.type = "none";
if (edit_accs.Count == 0)
{
break;
}
else
acc = edit_accs.Dequeue();
Od_post od_post = new Od_post(acc, proxy, Proxy.type);
string login = od_post.Auth();
if ()
{
string url = rand_url();
var text = new RandomString(Program.Data.textBox3).ToString();
string wall_post_text = od_post.wall_post_text(get_text(text), url);
if (wall_post_text == "Good")
{
string image_add = od_post.image_add(post_image_path);
if (image_add.Split('|')[0] == "Good")
{
if (Program.Data.checkBox5)
{
string change_name = od_post.change_name();
if (change_name == "Changed")
{
}
else
{
}
}
sync.Set();
return image_add.Split('|')[1];
}
else
{
}
}
else
{
}
}
else
{
lock (locker)
{
accs.Enqueue(acc);
Proxy.proxies.Remove(proxy);
}
}
}
return "Failed";
}
But it doesn't work. My app hangs, and the post doesn't receive the return value from create_note(). Why?
thr[0].Start();
sync.WaitOne();
This is a pretty common mistake when using a thread. Threading can give you two benefits. One is that code can run concurrently, allowing you to get more work done if you have a machine with multiple cores. And more commonly, it can run code asynchronously, a consideration when you have a user interface that you want to keep responsive.
You are getting neither. It does not run concurrently, your main thread isn't doing any work since it is waiting for the thread to complete. And it doesn't run asynchronously either, your main thread is frozen while the thread is doing its job.
You instead get all the disadvantages of a thread. A classic threading bug is a "race", your code has one. You hope that the "post" variable is assigned after the WaitOne() method completes. It might be, but the odds are just not that good. Since you call Set() before the assignment executes. It can only work correctly when you call Set() after the assignment. Deadlock is another classic threading bug, I don't see one but your debugger can easily show you. Deadlock is very likely here because you are freezing your main thread. Making calls like Invoke() on the thread is going to deadlock.
There's a very simple substitute for your code that does everything that you hope your current code does, minus the threading bugs:
string post = create_note();
Problem solved.
Minus addressing the reason that you considered writing this code in the first place. Which does require that you move all of the code that's now after the WaitOne() call into a callback that runs when the thread completes. Such code tends to be difficult to write, dealing with asynchronicity isn't that easy. But you can get help from .NET to get this right, like the BackgroundWorker.RunWorkerCompleted event, the Task class with its TaskScheduler.FromCurrentSynchronizationContext() method. And the async keyword added to C# version 5.
I'm using parallel.for to launch in many threads a external program. But despite the fact that these are separate threads I need implement sth like delay. E.g. 2 threads want to launch this external program at the same moment - then one of them should wait and start e.g. 10 sec after second thread.
Is it possible?
It's possible, but given the information you've provided it seems pointless... you're enforcing single-threaded execution of the external program, so you might as well have a single thread executing it. If Thread 2 has to wait for Thread 1 in order to start the "external program," then just let Thread 1 do all the work since it already knows when it started the "external program."
The only benefit you will get from a multi-threaded approach is if you have a bunch of processing that you need to do prior to executing the "external program" and that processing has to be a good candidate for concurrent execution.
Update
OK, there are a couple of ways to do this with only one extra thread in order to keep your Main/GUI thread responsive. The first approach is a simple lock around the external resource which you're interacting with:
public class ExternalResourceHandler
{
private readonly ExternalResource _resource;
private readonly object _sync = new object();
// constructors
// ...
// other methods
public void PerformExternalOperation()
{
lock(_sync)
{
Result result = _resource.Execute();
// do soemthing with the result
}
}
}
Here are 3 multi-threaded version for executing the code:
Using a Parallel.For method: recommended if the external program takes a short amount of time to execute- I'd suggest for things under 25 seconds (although this is not necessarily a "correct" number).
Using a ThreadPool: again, I'd recommend for things that take less than 25 seconds (with the same reservation as above).
Using a Thread: this would be recommended if the operation runs longer (i.e. more than 25 seconds, but it would do just as good if it's under 25 seconds).
Here are some examples (not necessarily functional, mostly meant to give you an idea of the different approaches):
public class Program
{
public static ExternalResourceHandler _erh = new ExternalResourceHandler();
static int Main()
{
Console.WriteLine("Type 'exit' to stop; 'parallel', 'pool' or 'thread' for the corresponding execution version.");
string input = Console.ReadLine();
while(input != "exit")
{
switch(input)
{
case "parallel":
// Run the Parallel.For version
ParallelForVersion();
break;
caase "pool":
// Run the threadpool version
ThreadPoolVersion();
break;
case "thread":
// Run the thread version
ThreadVersion();
break;
default:
break;
}
input = Console.ReadLine();
}
return 0;
}
public static void ParallelForVersion()
{
Parallel.For(0, 1, i =>
{
_erh.PerformExternalOperation();
});
}
public static void ThreadPoolVersion()
{
ThreadPool.QueueUserWorkItem(o=>
{
_erh.PerformExternalOperation();
});
}
public static void ThreadVersion()
{
Thread t = new Thread(()=>
{
_erh.PerformExternalOperation();
});
t.IsBackground = true;
t.Start();
}
}
The other option is to employ the Producer/Consumer design pattern where your ExternalResourceHandler is the consumer and it processes requests to the external resource from a thread-safe queue. Your main thread just places requests on the queue and immediately returns back to work. Here is an example:
public class ExternalResourceHandler
{
private volatile boolean _running;
private readonly ExternalResource _resource;
private readonly BlockingQueue<Request> _requestQueue;
public ExternalResourceHandler( BlockingQueue<Request> requestQueue)
{
_requestQueue = requestQueue;
_running = false;
}
public void QueueRequest(Request request)
{
_requestQueue.Enqueue(request);
}
public void Run()
{
_running = true;
while(_running)
{
Request request = null;
if(_requestQueue.TryDequeue(ref request) && request!=null)
{
_resource.Execute(request);
}
}
}
// methods to stop the handler (i.e. set the _running flag to false)
}
Your main would look like this:
public class Program
{
public static ExternalResourceHandler _erh = new ExternalResourceHandler();
static int Main()
{
Thread erhThread = new Thread(()=>{_erh.Run();});
erhThread.IsBackground = true;
erhThread.Start();
Console.WriteLine("Type 'exit' to stop or press enter to enqueue another request.");
string input = Console.ReadLine();
while(input != "exit")
{
_erh.EnqeueRequest(new Request());
input = Console.ReadLine();
}
// Stops the erh by setting the running flag to false
_erh.Stop();
// You may also need to interrupt the thread in order to
// get it out of a blocking state prior to calling Join()
erhThread.Join();
return 0;
}
}
As you see: in both cases all the work for the external handler is forced on a single thread yet your main thread still remains responsive.
Look at producer-consumer pattern. The first thread produces the information "external progam launched" the second thread consumes it, waits 10 second and then launches the external program.
I know I can use ReadKey for that but it will freeze the app until user presses a key. Is it possible (in console app) to have some loop running and still be able to react? I can only think of events but not sure how to use them in console.
My idea was that the loop would check for input during each iteration.
They way I have done this for my own application was to have a dedicated thread that calls into System.Console.ReadKey(true) and puts the keys pressed (and any other events) into a message queue.
The main thread then services this queue in a loop (in a similar fashion to the main loop in a Win32 application), ensuring that rendering and event processing is all handled on a single thread.
private void StartKeyboardListener()
{
var thread = new Thread(() => {
while (!this.stopping)
{
ConsoleKeyInfo key = System.Console.ReadKey(true);
this.messageQueue.Enqueue(new KeyboardMessage(key));
}
});
thread.IsBackground = true;
thread.Start();
}
private void MessageLoop()
{
while (!this.stopping)
{
Message message = this.messageQueue.Dequeue(DEQUEUE_TIMEOUT);
if (message != null)
{
switch (message.MessageType)
{
case MessageType.Keyboard:
HandleKeyboardMessage((KeyboardMessage) message);
break;
...
}
}
Thread.Yield(); // or Thread.Sleep(0)
}
}
Have the loop run in separate thread.
class Program
{
private static string input;
public static void Main()
{
Thread t = new Thread(new ThreadStart(work));
input = Console.ReadLine();
}
private static void work()
{
while (input == null)
{
//do stuff....
}
}
}
Try KeyAvailable property starting with .NET Framework 2 through now (current .NET 6 - including .NET Core). A single thread can process in a loop without being blocked.
// loop start
if (Console.KeyAvailable) // Non-blocking peek
{
var key = Console.ReadKey(true);
// process key
}
// continue without stopping
// loop end