This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Synchronization Problem for SAPI or (text to speech ) … C#
I've made a browser with WebControl. Now I want to read and highlight the text. So I split then sentences and start a loop.now the problem is, with a Synchronous call of SAPI to speak the sentences, every other button of the browser stops working. I can't pause, resume or even exit the software. Every button get hanged.
If I use a asynchronous call of SAPI, this problem doesn't occur, but then the highlighting of text will not work. So, I need to stick with this Synchronous call and also get over with this hang problem. Does anyone have any solution!!!!!!!
for (int i = 0; i < splitSentences.Length; i++)
{
highlight(splitSentences[i]);
sound_object.Speak(splitSentences[i]);
}
Please urgent help needed. How can I work out those pause, exit buttons of browser while speaking the sentece....
I think you should use Invoke in HighLight function.
For example,
void Do() //Must be start in another thread, not in main
{
string [] splitSentences = new [] {"bye", "hello"};
for (int i = 0; i < splitSentences.Length; i++)
{
HighLight(splitSentences[i], this);
sound_object.Speak(splitSentences[i]);
}
}
void HighLight(string str, Control webBrowser)
{
if (this.InvokeRequired)
{
this.Invoke(new Action<string>(s, c => HighLight(s, c)));
}
// Highlight code here
}
Related
This question already has answers here:
How to create a Flashing and Normal Background Visual States for a Border control
(2 answers)
Closed 22 days ago.
I have been trying to get a border in my wpf application(c#) to flash red and blue when you input the wrong password.
my code:
//This method executes when you enter the wrong password
void Alert()
{
Count = 0;
while (Count <= 5)
{
Border_.BorderBrush = Brushes.DarkRed;
//Timer here
Border_.BorderBrush = Brushes.DarkBlue;
//Timer here
Count++;
}
}
I have tried using await, Thread.Sleep(1000), Task.Delay(1000) and Timers but nothing worked. I searched for any similar question but could not find any solution that worked for me. (This question didnt work for me either: How to create a Flashing and Normal Background Visual States for a Border control)
This is the code-behind example, without visual states;
public Task Alert()
{
return Task.Run(() =>
{
int Count = 0;
while (Count <= 5)
{
Application.Current.Dispatcher.Invoke(() => Border_.BorderBrush = Brushes.DarkRed);
//Timer here
Thread.Sleep(1000);
Application.Current.Dispatcher.Invoke(() => Border_.BorderBrush = Brushes.DarkBlue);
//Timer here
Thread.Sleep(1000);
Count++;
}
});
}
And you can call with;
await Alert();
Also, do not forget to set BorderThickness.
Forgive me if this is simple. I come from the Embedded RToS world and have learnt c# for just for the purpose of test equipment for production. I think I have solved all the obvious issues already, just the tasks are not acting as expected.
I have a test jig with 10 serial ports and other things attached and a very basic windows forms UI with 10 list box's that need to all run simultaneously. I have cut the code down to just what is needed for the demo of the problem (no serial ports etc)
I am unable to get 10 listbox's (or textboxs) to update from 10 tasks properly. I can easily do one at a time, even 5 works, but 10 and it does not work.
I was getting exception out of range as it somehow gets passed a 10, but I only pass 0-9 so I reduced the task count to 9 for now until I understand the fundamental issue(s).
private void buttonStart_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() => PTT.ProductionTest());
}
This is the task from the PTT class, it will manage and monitor the 10 tasks so the UI is still responsive
public static void ProductionTest()
{
//Somewhere to store the tasks
List<Task> TestSlotTasks = new List<Task>();
//Create the tasks for each of the test slots
for (int i = 0; i != 9; ++i)
{
TestSlotTasks.Add(Task.Factory.StartNew(() => new PTT().TestSlot(i)));
Program.ListBoxAddLine(string.Format("CALL[{0}]: task start/stop test", i), System.Drawing.Color.LawnGreen, i);
}
Task.WaitAll(TestSlotTasks.ToArray());
}
This is supposed to be a non static program so I can create multiple instances (so I can run it many times without issue, that is my intention anyway, right?)
private void TestSlot(int slot)
{
for (var z = 0; z != 10; ++z)
{
Program.ListBoxAddLine(string.Format("PTT[{0}]: task start/stop test", slot), System.Drawing.Color.LawnGreen, slot);
}
}
This is the invoke method i use to update the listBox. The list box is in a generic list something like this
//ListBoxs.Add(listBoxSlot1); //Done for each of the 10 list box's to put in a list
//This is the method that will add a line to the main text box and to the log file
public static void ListBoxAddLine(string TextToAdd, System.Drawing.Color textColor, int slot)
{
//Update the list box on the main screen
if (mainForm != null)
{
if (FormPTT.ListBoxs[slot].InvokeRequired)
{
FormPTT.ListBoxs[slot].Invoke((MethodInvoker)delegate ()
{
FormPTT.ListBoxs[slot].ForeColor = textColor;
FormPTT.ListBoxs[slot].TopIndex = FormPTT.ListBoxs[slot].Items.Add(TextToAdd);
});
}
else
{
FormPTT.ListBoxs[slot].ForeColor = textColor;
FormPTT.ListBoxs[slot].TopIndex = FormPTT.ListBoxs[slot].Items.Add(TextToAdd);
}
}
}
The output I get is pretty random if i go above 5 or 6 list box's for this example.
Using the above code, I get this
output in the list box's, ignore the other stuff
So its all ok up until slot 8, its shows the Call[7] task start/stop but nothing from the task call and 9 and 10 are ok, but I dont call it 10 times, so how is 10 getting updated? I dont pass 10? and where is 8's PTT[7]... output?
I assume I am just not understanding a few things about tasks...
I am writing a piece of code that takes a user through a guided script. The user will have a few seconds to answer before the answer will be displayed.
So far, my code looks like this:
GuidedExercise3 exercise3 = new GuidedExercise3();
string AntonioAnswer = string.Empty; // expected answer
int upperBound = exercise3.Script.Count - 1; // zero-based counting
for(int i = 0; i < upperBound; i += 2)
{
labelInstructions.Text = exercise3.Script[i].TextToSpeak;
AntonioAnswer = exercise3.Script[i+1].TextToSpeak; // answer
SetTimer(AntonioAnswer, txtAntonio); // set timer sending in the answer and the TextBox object.
sysTimer.Start();
}
The odd lines of a List contain the question and the even lines contain the expected answer. My question is how do I display the question for X seconds and then get the user's answer in this WinForms app and then display the answer when the timer elapses, keeping the user from going to the next step of the script but allowing them to answer the question (which is in a Textbox).
I examined this StackOverflow question, but it doesn't match: Implementing a loop using a timer in C#
Here's how I would handle something like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
MoveNextQuestion();
timerAnswer.Interval = 5000;
timerAnswer.Start();
}
private string[] _questionsAndAnswers = new[]
{
"What colour is the sky?",
"Blue",
"What do chickens lay?",
"Eggs",
};
private int _currentIndex = -2;
private void timerAnswer_Tick(object sender, EventArgs e)
{
MoveNextQuestion();
}
private void buttonAnswer_Click(object sender, EventArgs e)
{
MoveNextQuestion();
}
private void MoveNextQuestion()
{
_currentIndex += 2;
if (_currentIndex < _questionsAndAnswers.Length)
{
labelQuestion.Text = _questionsAndAnswers[_currentIndex];
}
else
{
timerAnswer.Stop();
}
}
}
I was able to get this working fairly easily with a BackgroundWorker object. See the following article at MSDN for the exact coding. BackgroundWorker Class. In particular they have two examples in the documentation and the first example is sufficient. The BackgroundWorker class is allowing my UI to continue to accept user input while waiting on a timed answer. It displays the correct answer on the RunWorkerComplete event. So the BackgroundWorker's RunAsync gets called in my for loop.
I've run into the additional issue of the BackgroundWorker not returning control to my loop. I'm looking into that problem separately.
This question already has answers here:
How do you add a timer to a C# console application
(12 answers)
Closed 2 years ago.
This is an old question that I have come back to fix/edit, the essence of the question was how to implement a timer properly which has been answerd many times, so i have marked this as a duplicate
Link to a good answer for implementing a timer:
How do you add a timer to a C# console application
Use a Timer. In your catch, do not do the error message, instead, create a Timer object. Add to that timer's elapsed event a handler that will display the message only if the value is still invalid.
catch (FormatException fEX)
{
if (MyFormatExcTimer == null) {
MyFormatExcTimer = new Timer(1000);
MyFormatExcTimer.elapsed += async ( sender, e ) => await HandleTimer();
MyFormatExcTimer.start();
}
}
private static Task HandleTimer()
{
if (... format is still bad ...)
{
Message.Box("Value must be a divisisable by 1 exactly");
} else {
MyFormatExcTimer.Stop();
}
MyFormatExcTimer.Dispose();
MyFormatExcTimer = null;
}
This is not very complete. You may need to create or dispose or start or stop the timer at different events, but without seeing more of your code it is hard to tell. I might actually not have the program fire off an exception on bad input, but accept any input and have my own code that tests it. My code would get fired off on any text changed event and could set off the timer if the input is bad or stop it if the input is ok.
Also, you might consider not even firing off any messages during input, but rather firing verifying the data when the user tries to save it... but that assumes you have a "save" button or something like that, which you may not.
I agree with the #CodeCaster's comment that message box is not the best way to communicate invalid input to the user, but here is how it can be done:
//declare DateTime lastErrMsg = DateTime.MinValue; at your class level
catch (FormatException fEX)
{
if (DateTime.Now - lastErrMsg > TimeSpan.FromSeconds(30)) //or whatever TimeSpan value
{
Message.Box("Value must be a divisisable by 1 exactly")
lastErrMsg = DateTime.Now;
}
}
I have recently implemented a scrolling text across an area of limited screen estate using a timers repeating every 100ms, and some simple string appending.
However, after this very implementation, I have come to realise that my GUI is getting randomly bugged/corrupted after a certain while. That is to say that some widgets/windows become completely white, and eventually the entire GUI turns white and unclickable.
What is weird is that there is no error debug output at all.
Having said that, I am using Mono with GTK-Sharp for the application. Does anyone have an idea or a possible clue how and why this is happening?
If not, how can I further debug this properly?
Thanks, really appreciate it.
PS: Sometimes, it takes up to 1.5 hours for the thing to start corrupting, it has random timeframes for it to start happening.
This is my the code implemented that caused this issue:
void ScrollSyncTo(object sender, System.Timers.ElapsedEventArgs e)
{
//initial check if it fits nicely alr
if (sync_to_full_txt.Length <= sync_to_max_char)
{
sync_to_timer.Stop();
return;
}
//check for pause
if (sync_to_pause >= 0)
{
sync_to_pause--;
return;
}
//check direction
int temp_psn;
string temp_str;
if (sync_to_direction)
{
temp_psn = sync_to_posn + 1;
if (sync_to_full_txt.Substring(temp_psn).Length < sync_to_max_char)
{
sync_to_pause = sync_to_break_steps;
sync_to_direction = false;
sync_to_posn = sync_to_full_txt.Length - 1;
System.GC.Collect();
return;
}
else
{
temp_str = sync_to_full_txt.Substring(temp_psn, sync_to_max_char);
}
}
else
{
temp_psn = sync_to_posn - 1;
if (temp_psn + 1 < sync_to_max_char)
{
sync_to_pause = sync_to_break_steps;
sync_to_direction = true;
sync_to_posn = 0;
System.GC.Collect();
return;
}
else
{
temp_str = sync_to_full_txt.Substring(temp_psn - sync_to_max_char + 1, sync_to_max_char);
}
}
//lets move it
sync_to.Text = temp_str;
sync_to_posn = temp_psn;
}
To program in GTK with multiple threads, you have to do a couple things to make your program thread-safe. Here is short explanation using C.
I'm more familiar with GTK in C, but I'm assuming it works the same in GTK#. So you have to call GLib.Thread.Init() and Gdk.Threads.Init() at the beginning of your program, bracket your call to Application.Run() with Gdk.Threads.Enter() and Gdk.Threads.Leave(), and also make sure any GTK and GDK calls in background threads (not GTK signal handlers) are between Gdk.Threads.Enter() and Gdk.Threads.Leave().
System.Timers.Timer callbacks come from a threadpool thread, but GTK objects can only safely be accessed from the GTK thread. I would suggest using GLib.Timeout, which runs on the GTK thread.