Locking thread in C# - c#

In my C# project I m using the Timer.One(keyboard_timer) is for to watch if a user press F8 or not and another Timer(clipboard_time) is to watch if Clipboard contains a text or not.In my project The keyboard is always enable and the clipboard_timer is enabled when a user press F8.If the user again press F8 the clipboard_timer is disabled.what my project does that When user press F8 and he copies a word then my project show the meaning of the copied word in a window.my program runs on the background and always check if a user press F8 if he does then all-time my program check the clipboard, if it contains a text(word) if it does the show the meaning of the word everytime.
My code is here:
On the initialize
keyboard_timer.Enabled = true;
keyboard_timer.Tick += new EventHandler(keyboard_timer_Tick);
then
public void keyboard_timer_Tick(object sender, EventArgs e)
{
// clipboard enable
if ((a % 2) != 0)
{
// F9 is for Easy mood to eanble
if ((GetAsyncKeyState(Keys.F9) == -32767) && hot_key == "F9")
{
label2.Text = "Easy";
online_clipboard_active = "";
Clipboard.Clear();
clipboard_timer.Enabled = true;
clipboard_timer.Tick += new EventHandler(clipboard_timer_Tick);
++a;
}
///// // F8 is for online Mood
else if ((GetAsyncKeyState(Keys.F8) == -32767) && online_hot_key == "F8")
{
label2.Text = "Online";
online_clipboard_active = "on";
clipboard_timer.Enabled = true;
clipboard_timer.Tick += new EventHandler(clipboard_timer_Tick);
++a;
}
}// end of enable
//clipboard disable
if ((a % 2) == 0) //
{
// F9 is for Easy mood to disable here
if ((GetAsyncKeyState(Keys.F9) == -32767) && hot_key == "F9")
{
label2.Text = "Off";
clipboard_timer.Enabled = false;
++a;
}
// F8 is for online Mood to disable here
else if ((GetAsyncKeyState(Keys.F8) == -32767) && online_hot_key == "F8")
{
label2.Text = "Off";
online_clipboard_active = "";
clipboard_timer.Enabled = false;
++a;
}
}//end of clipboard disable
}// end of keyboard timer
Clipboard timer is
public void clipboard_timer_Tick(object sender, EventArgs e)
{
if (Clipboard.GetDataObject().GetDataPresent(DataFormats.Text))
{
string x = Clipboard.GetText();
Clipboard.Clear();
if ((a%2)==0 && online_clipboard_active == "on")
{
//cal online_mood form to translate the string from googletranslator
online_mood o = new online_mood(x);
o.Show();
}
else if((a%2)==0 && online_clipboard_active == "")
{
//cal show_meaning form to show the meaning into a window
show_meaning s = new show_meaning(x);
s.Show();
}
}
}// end of clipboard timer Tick
I want that when clipboard timer enable on that time keyboard timer will be lock because both of them uses a variable. When clipboard timer runs then keyboard timer will be lock and then when clipboard timer finished it works then the keyboard timer will be reactivated How can I solve this?
Anyone give me any help?????

Simple locking can be accomplish with a static member.
private static readonly object Sync = new object();
and then before setting or getting the info use
lock(Sync)
to lock the variable.
BTW: I don't get what you are trying to do. Maybe you should use the Keypress event of the form instead of the timers.

Look into C# locks
you basicly do this:
public Object lockObject = new Object(); //You want a separate object so that it's not changed when lock is active
...
//Code that can be run by any number of thread at the same time
...
lock(lockObject)
{
...
//Code that is accessable by only one thread at a time:
...
}
...
//Code that can be run by any number of thread at the same time
...
Hope this helps you out a bit.

Related

ListView keeps repeating/showing same text because of timer

I'm making a program to send data true USB. In my program I'm making a list view to show what the program is currently doing.
because I'm working with USB I have a timer with a interval of 50, this causes problems when I want to send text to my list view because my text is send 50 times per second in stead of 1 time.
Anyone any idea how to solve this?
Changing my program so when a text is already written in the listbox the program may not send it again is not an option I think because the same action can happen more than 1 time.
Here you can find relevant code.
private void ClickMyRadioButton1()
{
if (radioOff1.Checked)
{
radioOff1.PerformClick();
ListViewItem lvi = new ListViewItem("All USB's are off");
listView1.Items.Add(lvi);
}
}
private void tmrUSB_Tick(object sender, EventArgs e)
{
//Everything in here is repeated constantly
USBObject.receiveViaUSB();
listView1.EnsureVisible(listView1.Items.Count - 1);
if ( tabPage1 == tabControl1.SelectedTab)
{
this.radioOff2.Checked = true;
if (radioOff1.Checked == true)
{
USBObject.fromHostToDeviceBuffer[1] = USB_OFF;
ClickMyRadioButton1(); //This is what I only want to send one time to my ListBox and not 50 times a second
}
}
I'm using Visual C# 2010.
Thanks
try this, let me know if it works for you:
private void ClickMyRadioButton1()
{
if (radioOff1.Checked)
{
radioOff1.PerformClick();
ListViewItem lvi = new ListViewItem("All USB's are off");
listView1.Items.Add(lvi);
}
}
int counter = 0;
private void tmrUSB_Tick(object sender, EventArgs e)
{
if (counter != 50)
{
counter++;
return;
}
else
{
counter = 0;
}
//Everything in here is repeated constantly
USBObject.receiveViaUSB();
listView1.EnsureVisible(listView1.Items.Count - 1);
if ( tabPage1 == tabControl1.SelectedTab)
{
this.radioOff2.Checked = true;
if (radioOff1.Checked == true)
{
USBObject.fromHostToDeviceBuffer[1] = USB_OFF;
ClickMyRadioButton1(); //This is what I only want to send one tine to my ListBox
}
}

C# BackgroundWorker Completed Called Way Before Completion

I have been trying to work out why my background worker is 'finishing' its work when there is still a lot for it to do. I am actually in the process of refactoring the code for this app, so it did work in the past, but now I am unable to figure out what has gone wrong.
Specifically, the app should open Outlook and then perform a few checks. However, the background worker exits straight after Outlook is opened for no apparent reason (as you will se below there is still plenty of processing to be done).
This appears to be happening early on in the Start() method, directly after calling Process.Start() on Outlook.exe.
The code runs in this order:
calling the background worker - this was the user's choice from a radio set
....
else if (radioButton5.Checked == true)
{
textBox1.Text = "Please wait while your session restarts";
pageControl1.SelectedIndex = 10;
backgroundReset.RunWorkerAsync();
}
The do-work method
public void backgroundReset_DoWork(object sender, DoWorkEventArgs e)
{
backgroundReset.WorkerSupportsCancellation = true;
Session.Reset();
}
the reset session method starts by killing the current session ...
public static void Reset()
{
KillSession();
System.Threading.Thread.Sleep(5000);
Start();
// THE BACKGROUNDWORKER EXITS BEFORE HERE!
if (IsLoggedIn() == false)
{
return;
}
else
{
// Make sure Lync is open before finishing the process ...
var j = 0;
GetSession(Init.servers);
j = 0;
var checker = false;
checker = ProcessHandler.CheckRunning("lync.exe");
while (checker == false)
{
if (j == 100)
{
break;
}
Thread.Sleep(500);
checker = ProcessHandler.CheckRunning("lync.exe");
j++;
}
}
}
As you can see from the comment, the backgroundworder is calling RunWorkerCompleted way before the Reset() method has finished executing.
Below are the other methods called (kill, logoff, start):
KillSession logs the session of and then makes sure it is logged off
private static void KillSession()
{
if (sessionId != null)
{
LogOff();
for (int i = 0; i < 150; i++)
{
if (IsLoggedIn() == true)
{
Thread.Sleep(500);
}
else
{
break;
}
}
}
}
LogOff sends a Cmd command to log off the current session
public static void LogOff()
{
string strCmdIn = "/C LOGOFF " + sessionId + " /SERVER:" + serverName;
Cmd.Exec(strCmdIn);
}
Start() Simply opens Outlook, causing a Citrix session to also start. The app is definitely launching Outlook, but after that it doesn't reach either of the for statements - the BackgroundWorker just exits.
public static void Start()
{
Process.Start(appDataCitrix + "Outlook.exe");
for (int i = 0; i < 15; i++)
{
if (IsLoggedIn2() == false)
{
Thread.Sleep(1000);
}
else
{
break;
}
}
if (IsLoggedIn2() == false)
{
Process.Start(appDataCitrix + "Outlook.exe");
for (int i = 0; i < 10; i++)
{
if (IsLoggedIn2() == false)
{
Thread.Sleep(1000);
}
else
{
break;
}
}
}
}
Does anyone have any idea what is going on here? It is driving me crazy!
Many thanks
Update
The RunWorkerCompleted Method:
As far as my understanding goes, this has no baring on when the process will finish.
public void backgroundReset_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (Session.IsLoggedIn())
{
btnFailFinish.Visible = true;
label10.Text = Session.serverName;
pageControl1.SelectedIndex = 3;
}
else
{
pageControl1.SelectedIndex = 10;
pictureBox2.Visible = false;
textBox1.Text = "Double-click Outlook on your desktop to launch a new session.";
textBox15.Text = "Once you have done this please click Finish.";
pictureBox9.Visible = true;
}
}
This is probably because of an exception being thrown from within the start method.
You may either add a try / catch block all around this method and handle the error from within the catch, or check in the RunWorkerCompleted method if an exception occurred :
private void RunWorkerCompleted (object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
// handle your exception here
}
}

Button_click in windows form

I have this button5 function below. What I want is when the use wants to click button1 after clicking button5 the while loop in button5 should break, because the choice is now 1. Choice is a global variable set to zero at the start. While the button5 function is running the button1 function will not be called on click. How to solve this problem?
This is the Answer Thanks Everyone For the Help!!
private Thread demoThread = null;
delegate void SetTextCallback(string text);
private void button1_Click(object sender, EventArgs e)
{
choice = 1;
System.Console.WriteLine(choice);
}
private void button5_Click(object sender, EventArgs e)
{
//button1.Enabled = false;
button5.Visible = false;
panel2.Visible = true;
panel1.Visible = true;
panel3.Visible = true;
label2.Visible = true;
button1.Visible = true;
button2.Visible = true;
button3.Visible = true;
button4.Visible = true;
this.demoThread = new Thread(new ThreadStart(this.StartForLoop));
this.demoThread.Start();
}
private void StartForLoop()
{
while (choice != 1 || choice != 2 || choice != 3)
{
if (choice == 1 )
{
choice = 1;
break;
}
if (choice == 2)
{
choice = 2;
break;
}
if (choice == 3)
{
choice = 3;
break;
}
Application.DoEvents();
}
System.Console.WriteLine("AAA");
if (choice == 3)//why
{
}
if (choice == 1)//true
{
System.Console.WriteLine("label");
this.SetText("Does the animal lay eggs?");
}
if (choice == 2)//false
{
}
}
This is a wrong concept. Never use Application.DoEvents();, it's a hack. It does not solve any of your problems.
You do not need a while loop in Button5_Click. Everything in that loop could be handled by code in your other click handler.
Your problem can probably be solved by a state machine. This looks complicated, but it#s not. Try to implement it as simple as possible and ask another question when you encounter problems.
You have a problem with Thread's, the problem is that you program Thread is busy in the loop of your button5 and until it finishes handling button5 code, your thread will not pay attention to more anything.
To solve this, you must run your while loop inside of new thread like this:
Thread t = new Thread (new ThreadStart(delegate(){
//while goes here along with the if's...
}));
t.Start();
In your button1, when you change the value of your global variables
the code inside of a thread launched in the button5 will now be aware of
your changes and behave accordingly.
Also be very careful with the following, since choice is a global variable
it can be access by two threads now at the same time, the program thread
and your new thread, because of this ensure you access the choice variable
with mutexs, in c# you can access a thread shared variable like this:
//declare this next to your choice variable.
Object mux_choice = new Object();
lock(mux_choice){
//changing choice here is thread safe.
}
Since choice seems to be a value type, you must create a object representing the access to your value type variable (http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx).
You have more info about threads in C# here:
http://www.albahari.com/threading/
Note: Make sure you protect the choice variable everywhere it is used.
Also, from your comments I assume that you want to modify the Form controls
properties, like label2.Text="..." becarefull with that, you will face Cross Thread Exceptions if you do that. To modify a Controls property you must call the Invoke method, that invokes the change in the UI thread, like this:
label2.Invoke((MethodInvoker)(() => label2.Text = "some text"));
Depending on the .NET framework version, here is a code compatible with .NET 2.0:
label2.Invoke(new MethodInvoker(delegate(){ label2.Text = "some text"; }));
Regards.
The best way is to run a for each loop into another thread so it will not disturb the UI of form.
and user can easily click on button 1.
like just for basic idea :
private void button5_Click(object sender, EventArgs e)
{
button5.Visible = false;
panel2.Visible = true;
panel1.Visible = true;
panel3.Visible = true;
label2.Visible = true;
button1.Visible = true;
button2.Visible = true;
button3.Visible = true;
button4.Visible = true;
Thread thread = new Thread(new ThreadStart(StartForLoop));
thread.Start();
}
public void StartForLoop()
{
while (choice != 1 || choice != 2 || choice != 3)
{
if (choice == 1 || choice == 2 || choice == 3)
{
choice = 1000;
break;
}
Application.DoEvents();
}
if(choice==3)//why
{
}
if(choice==1)//true
{
label2.Text = "asdasd";
}
if(choice==2)//false
{
}
}
PS : better to implement lock on choice as well

Boolean Statement True For Length of Time

I have the following code:
private Boolean _penny = false;
public void InputTextbox_KeyDown(object sender, KeyEventArgs e)
{
if (!_penny)
{
if (e.KeyCode == Keys.Enter & InputTextbox.Text.Contains("penny"))
{
_penny = true;
OutputTextbox.Text = "yes sir";
InputTextbox.Text = "";
}
}
}
This clears the InputTextbox so that it is ready for further input, and the commands that follow only run if the Boolean for _penny = true (ie: that the program has been ordered to listen for further commands).
At the moment, each text command ends with "_penny == false" so that the program essentially stops listening for anything.
My question is, can this Boolean value stay "true" for a length of time? ie: User says "penny", and they can ask multiple input questions for a number of minutes without having to say "penny" again.
While you could use a timer, that seems like overkill to me. All you need to do is track an expiry date/time:
private bool CurrentlyValidated
{
get
{
return DateTime.Now < _expiryTime && _validated ;
}
set
{
_validated = value ;
_expiryTime = DateTime.Now.AddMinutes(5) ;
}
}
private bool _validated ;
private DateTime _expiryTime ;
I used Nicholas Carey's solution, but slightly modified; for anyone who wants it here it is:
private DateTime _expiryTime;
public void InputTextbox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter && InputTextbox.Text.Contains("penny"))
{
_expiryTime = DateTime.Now.AddMinutes(1);
OutputTextbox.Text = "yes sir";
}
else if (e.KeyCode == Keys.Enter && InputTextbox.Text.Contains("what time is it") && DateTime.Now < _expiryTime)
{
code runs here...
}
This sets the _expiryTime to when the word "penny" is entered into the Textbox. The user can then run any of the following commands they like for 1 minute.

Windows form takes time to respond

I'm building a pretty big Winforms application. Everything worked fine, but in the past two days I'm have problems with times. For example, if I am running a loop that opens 8 tabs and creates a webbrowser in each, it takes it some time. The UI is kind of unresponsive while the function is running, but the big problem isn't in the creating.
I have a button that responsible for removing all the things I don't need from the UI(i.e. resetting it to the normal state). It just takes a huge time when there are about 10 tabs open. I measured the time and the time it takes the code to execute is about 1-1.2 seconds, but the time it takes to the UI to get responsive and preform everything I did is a lot more, about 10 seconds.
here is a code example:
private void killGUI()
{
DateTime a = DateTime.Now;
TimeSpan b;
this.SuspendLayout();
//tabPages.RemoveAll(TabPage);
tabPages.Clear();
if (tabControl1.TabPages.Count > 1)
{
//MessageBox.Show("" + tabControl1.TabPages.Count);
//DateTime a = DateTime.Now;
/*while (tabControl1.TabPages.Count != 1)
{
//int i = 1;
foreach (TabPage tab in tabControl1.TabPages)
{
if (tab.Name != "helpPanel")
{
tabControl1.TabPages.Remove(tab);
tab.Dispose();
}
}
}*/
while (tabControl1.TabPages.Count > 1)
{
Application.DoEvents();
TabPage t = tabControl1.TabPages[1];
tabControl1.TabPages.RemoveAt(1);
t.Dispose();
}
//TimeSpan v = DateTime.Now.Subtract(a);
//MessageBox.Show(""+v.Milliseconds);
}
///////
b = DateTime.Now.Subtract(a);
MessageBox.Show("REMOVING ALL TABS:" + a.Millisecond);
a = DateTime.Now;
////////
questions.ElementAt(0).richy.Dispose();
questions.ElementAt(0).createNewCom.Dispose();
//questions.ElementAt(questions.Count - 1).Name.Dispose();
for (int i = 0; i < questions.ElementAt(questions.Count - 1).comments.Count; i++)
{
Application.DoEvents();
if (questions.ElementAt(0).comments.ElementAt(i).texty != null)
questions.ElementAt(0).comments.ElementAt(i).texty.Dispose();
if (questions.ElementAt(0).comments.ElementAt(i).cButton != null)
questions.ElementAt(0).comments.ElementAt(i).cButton.Dispose();
Application.DoEvents();
}
/////
b = DateTime.Now.Subtract(a);
MessageBox.Show("REMOVING THIS QUESTION:" + a.Millisecond);
a = DateTime.Now;
/////
panel1.Visible = false;
while (panel2.Controls.Count != 0)
{
Application.DoEvents();
panel2.Controls.RemoveAt(0);
}
panel2.Visible = false;
backButton.Visible = false;
forwardButton.Visible = false;
//placePanel.Dispose();
//urgencyPanel.Dispose();
//categoriesPanel.Controls.Clear();
//categoriesPanel.Dispose();
//((Panel)((TabPage)tabControl1.Controls.Find("helpPanel", false)[0]).Controls.Find("placePanel", false)[0]).Dispose();
((Panel)((TabPage)tabControl1.Controls.Find("helpPanel", false)[0]).Controls.Find("categoriesPanel", false)[0]).Dispose();
((Panel)((TabPage)tabControl1.Controls.Find("helpPanel", false)[0]).Controls.Find("urgencyPanel", false)[0]).Dispose();
((Panel)((TabPage)tabControl1.Controls.Find("helpPanel", false)[0]).Controls.Find("placePanel", false)[0]).Dispose();
//Controls[] con=tabControl1.Controls.Find("HelpPanel",false);
newQuestionTextBox.Clear();
browsers.Clear();
panels.Clear();
buttons.Clear();
questions.RemoveAt(0);
finalTuid = "";
this.ResumeLayout();
foreach (Control cl in helpPanel.Controls)
{
Application.DoEvents();
if (cl.Name == "categoriesPanel" || cl.Name == "urgencyPanel" || cl.Name == "placePanel")
{
//WTF that shouldnt happen-i cant get this.
//MessageBox.Show("!!!");
cl.Dispose();
}
}
foreach (Control cl in helpPanel.Controls)
{
Application.DoEvents();
if (cl.Name == "categoriesPanel" || cl.Name == "urgencyPanel" || cl.Name == "placePanel")
{
//FFFFFFFFFFFUUUUUUUUUUUUUUUUUUU
//MessageBox.Show("!!!!!!!!");
cl.Dispose();
}
}
/////
b = DateTime.Now.Subtract(a);
MessageBox.Show("ALL ELSE:" + a.Millisecond);
///////
this.ResumeLayout();
}
also another probelm is if u can see:
((Panel)((TabPage)tabControl1.Controls.Find("helpPanel", false)[0]).Controls.Find("categoriesPanel", false)[0]).Dispose();
((Panel)((TabPage)tabControl1.Controls.Find("helpPanel", false)[0]).Controls.Find("urgencyPanel", false)[0]).Dispose();
((Panel)((TabPage)tabControl1.Controls.Find("helpPanel", false)[0]).Controls.Find("placePanel", false)[0]).Dispose();
This should remove three panels from the main panel, but it just doesn't work. I don't know why, but only after running the two loops below it removes the panels and just one loop isn't enough.
thanks so much in advance :)
Is there a reason why you don't have a reference to the help panel or the 3 other controls you want to dispose that exist in that panel? It seems really inefficient to have to iterate over the list of controls in your GUI (you said you had lots of tabs & controls) looking for these 3 specific controls. At bare minimum, you should cache the result of the helpPanel search as the next two lines are repeating the same search process that just occurred. The following loops can be solved with the same solution.
Wait, those two loops are iterating over helpPanel.Controls. So you already have a reference to the helpPanel and just not using it in the earlier steps?

Categories

Resources