tag:blogger.com,1999:blog-8259613.post7949509998309011667..comments2023-08-05T11:16:50.347+02:00Comments on Kristof Verbiest - Bite-size C#: Avoid Invoke(), prefer BeginInvoke()Kristofhttp://www.blogger.com/profile/01727380410232817527noreply@blogger.comBlogger20125tag:blogger.com,1999:blog-8259613.post-91007513878902559172010-06-21T04:31:57.692+02:002010-06-21T04:31:57.692+02:00This article helped me so much! I was running into...This article helped me so much! I was running into the same deadlock issue you had described and switching over to BeginInvoke cleared the issue right up! Thank you so much!Brandon Robertshttp://brokenwalls.netnoreply@blogger.comtag:blogger.com,1999:blog-8259613.post-68467753752464380752010-01-07T00:40:24.230+01:002010-01-07T00:40:24.230+01:00One reason why asynchronous might not be appropria...One reason why asynchronous might not be appropriate for updating UI is if the user clicks a button in a quick, repetitive fashion. In this case if you use BeginInvoke and the code you're invoking (my case was loading a document into a 3rd party view control) this might take too long and cause the requests to pile up. When the user finally paused their clicking so that the application could catch up the result was that the remaining scheduled beginInvokes executed in 'LastInLastOut' fashion. So they actually were looking a document that was from several clicks ago.<br /><br />Though, this 3rd party component was COM so perhaps this behavior was due to the extra layer.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-8259613.post-46068453035984275802009-08-13T10:02:33.249+02:002009-08-13T10:02:33.249+02:00@ear: if you really want synchronous behaviour, th...@ear: if you really want synchronous behaviour, then you'll have to use Invoke(). You could use BeginInvoke() in combination with a ManualResetEvent, but that is probably what Invoke() is doing behind the scenes as well.<br />But generally speaking, Invoke/BeginInvoke are mostly used to update the GUI. And why would you need to do this synchronously?Kristofhttps://www.blogger.com/profile/01727380410232817527noreply@blogger.comtag:blogger.com,1999:blog-8259613.post-91321188398025827752009-08-13T03:03:08.631+02:002009-08-13T03:03:08.631+02:00what if one wants synchronous behavoir? how to get...what if one wants synchronous behavoir? how to get this from BeginInvoke() ? Was thinking about System.Threading.ManualResetEvent but would prefer something simpler. any ideas?Unknownhttps://www.blogger.com/profile/06550374912486304334noreply@blogger.comtag:blogger.com,1999:blog-8259613.post-89693590449922873112009-08-11T09:29:56.627+02:002009-08-11T09:29:56.627+02:00@ear: the InvokeRequired-pattern is mostly used fo...@ear: the InvokeRequired-pattern is mostly used for simple GUI updates. It should not matter if this is synchronous or asynchronous. But if it does matter, then you might choose a mechanism that is more consist (e.g. always using BeginInvoke even if it is not entirely necessary).Kristofhttps://www.blogger.com/profile/01727380410232817527noreply@blogger.comtag:blogger.com,1999:blog-8259613.post-30249670471558380832009-08-10T18:25:13.650+02:002009-08-10T18:25:13.650+02:00Hi, I forgot to checkmark followup to my last comm...Hi, I forgot to checkmark followup to my last comment. Please followup to it! thanks!Unknownhttps://www.blogger.com/profile/06550374912486304334noreply@blogger.comtag:blogger.com,1999:blog-8259613.post-58561561044438796012009-08-10T18:23:31.999+02:002009-08-10T18:23:31.999+02:00There will be a bit of inconsistancy in the behavi...There will be a bit of inconsistancy in the behavior of methods too. If InvokeRequired is true it will have Async behavior else it'll be sync behavior!!! This could potentially cause problems.Unknownhttps://www.blogger.com/profile/06550374912486304334noreply@blogger.comtag:blogger.com,1999:blog-8259613.post-80891329887586144892009-06-03T11:06:29.798+02:002009-06-03T11:06:29.798+02:00Just to make it clear - don't use
CheckForIlle...Just to make it clear - don't use<br />CheckForIllegalCrossThreadCalls as I have been doing but call your method on the form with begininvoke. I think you cannot pass parameters so set them in the form variables. Example below.<br /><br />public void ShowMessage(string message)<br /> {<br /> // Use Begin invoke to avoid threading issues<br /> _showmessagebegininvoke = message;<br /> System.Threading.ThreadStart ts = ShowMessageBeginInvoke;<br /> BeginInvoke(ts, null);<br /> }<br /><br /> private void ShowMessageBeginInvoke()<br /> {<br /> //Control.CheckForIllegalCrossThreadCalls = false;<br /> string message = _showmessagebegininvoke;<br /> if (message == null) return;<br /><br /> if (this.txtmessage.Text.Length == 0)<br /> {<br /> this.txtmessage.Text = message;<br /> }<br /> else<br /> {<br /> this.txtmessage.Text = this.txtmessage.Text + Environment.NewLine + message;<br /> }<br /> _showmessagebegininvoke = null;<br /> //Control.CheckForIllegalCrossThreadCalls = true;<br /><br /> }Stamatihttp://www.redware.comnoreply@blogger.comtag:blogger.com,1999:blog-8259613.post-59598479781113689462009-06-03T11:04:09.572+02:002009-06-03T11:04:09.572+02:00Just to make it clear.... if you are having proble...Just to make it clear.... if you are having problems with threads on a control - don't use CheckForIllegalCrossThreadCalls as I have been doing but call the form method with BeginInvoke. I think you cannot pass parameters so set them up in form variables. Example below....<br /><br />public void ShowMessage(string message)<br /> {<br /> // Use Begin invoke to avoid threading issues<br /> _showmessagebegininvoke = message;<br /> System.Threading.ThreadStart ts = ShowMessageBeginInvoke;<br /> BeginInvoke(ts, null);<br /> }<br /><br /> private void ShowMessageBeginInvoke()<br /> {<br /> //Control.CheckForIllegalCrossThreadCalls = false;<br /> string message = _showmessagebegininvoke;<br /> if (message == null) return;<br /><br /> if (this.txtmessage.Text.Length == 0)<br /> {<br /> this.txtmessage.Text = message;<br /> }<br /> else<br /> {<br /> this.txtmessage.Text = this.txtmessage.Text + Environment.NewLine + message;<br /> }<br /> _showmessagebegininvoke = null;<br /> //Control.CheckForIllegalCrossThreadCalls = true;<br /><br /> }redwarenoreply@blogger.comtag:blogger.com,1999:blog-8259613.post-76610810123147983202009-01-29T10:07:00.000+01:002009-01-29T10:07:00.000+01:00Is there a way.. (any way) I can check if the hard...Is there a way.. (any way) I can check if the hardware is sucessfully connected to my computer through the serial PortAnonymoushttps://www.blogger.com/profile/15480996974552080094noreply@blogger.comtag:blogger.com,1999:blog-8259613.post-33616064120722407462009-01-28T12:57:00.000+01:002009-01-28T12:57:00.000+01:00To an extent it did solve my problem, but the thin...To an extent it did solve my problem, but the thing I've messed up is tht e is supposed to be of type EventArgs whereas I want an object of type SerialDataEventArgs.<BR/><BR/>BTW.. Thankx a lot for helping.. <BR/><BR/>U ROck!!Anonymoushttps://www.blogger.com/profile/15480996974552080094noreply@blogger.comtag:blogger.com,1999:blog-8259613.post-46295252450413271242009-01-28T12:45:00.000+01:002009-01-28T12:45:00.000+01:00@Sushi: I don't have the time to debug your code.B...@Sushi: I don't have the time to debug your code.<BR/><BR/>But at first sight, I find it a bit suspicious that you store your parameters in an object[], which is then stored in another object[].<BR/>Try changing your code to this:<BR/><BR/>this.BeginInvoke(new SerialDataReceivedEventHandler(sp_DataReceived),new Object[]{sender, e});<BR/><BR/>Note that you don't need the Para-object anymore.Kristofhttps://www.blogger.com/profile/01727380410232817527noreply@blogger.comtag:blogger.com,1999:blog-8259613.post-83250475842204517512009-01-28T12:08:00.000+01:002009-01-28T12:08:00.000+01:00namespace WindowsFormsApplication1{ public part...namespace WindowsFormsApplication1<BR/>{<BR/> public partial class Form1 : Form<BR/> {<BR/> PropertyPage pp = new PropertyPage();<BR/> public Form1()<BR/> {<BR/> InitializeComponent();<BR/><BR/> }<BR/> private void Form1_Load(object sender, EventArgs e)<BR/> {<BR/> MessageBox.Show("Serial Communication Test\n Sushant Khurana");<BR/> this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);<BR/> Object[] Para = new Object[2];<BR/> Para[0] = sender;<BR/> Para[1] = e;<BR/> try<BR/> {<BR/> this.BeginInvoke(new SerialDataReceivedEventHandler(sp_DataReceived),new Object[]{Para});<BR/> }<BR/> catch (Exception er)<BR/> {<BR/> MessageBox.Show(er.Message);<BR/> }<BR/> }<BR/> private void SStatus_Click(object sender, EventArgs e)<BR/> {<BR/> if (pp.bRate == "" && pp.sBits == "")<BR/> {<BR/> BRlabel.Text = "Baud Rate = " + sp.BaudRate.ToString();<BR/> DBlabel.Text = "Data Bits = " + sp.DataBits.ToString();<BR/> }<BR/> else<BR/> {<BR/> BRlabel.Text = "Baud Rate = " + pp.bRate;<BR/> DBlabel.Text = "Data Bits = " + pp.sBits;<BR/> }<BR/> Plabel.Text = "Parity = " + sp.Parity.ToString();<BR/> SBlabel.Text = "Stop Bits = " + sp.StopBits.ToString();<BR/> RTlabel.Text = "ReadTimeout = " + sp.ReadTimeout.ToString();<BR/> ComPrt.Text = "Port Name = " + sp.PortName.ToString();<BR/> if (Property.Visible == true)<BR/> Property.Hide();<BR/> SStatus.Hide();<BR/> StartCom.Show();<BR/> sp.ReceivedBytesThreshold = 3;<BR/> sp.ReadTimeout = SerialPort.InfiniteTimeout;<BR/> <BR/> }<BR/><BR/> private void Property_Click(object sender, EventArgs e)<BR/> {<BR/> pp.ShowDialog();<BR/> //Property.Hide();<BR/><BR/> }<BR/><BR/> private void Send_Click(object sender, EventArgs e)<BR/> {<BR/> BRlabel.Text = "";<BR/> try<BR/> {<BR/> sp.WriteLine(textBox.Text);<BR/> textBox.Text = "";<BR/> BRlabel.Text = "Text Sent Sucessfully\n";<BR/> }<BR/> catch(System.Exception ex)<BR/> {<BR/> BRlabel.Text = ex.Message;<BR/> }<BR/> }<BR/><BR/> <BR/> <BR/> private void Form1_FormClosing(object sender, FormClosingEventArgs e)<BR/> {<BR/><BR/> MessageBox.Show("Thankyou for using this Application!");<BR/> sp.Close();<BR/> }<BR/><BR/> private void StartCom_Click(object sender, EventArgs e)<BR/> {<BR/> //Reading Text <BR/> BRlabel.Text = "";<BR/> try<BR/> {<BR/> sp.DtrEnable = true;<BR/> sp.RtsEnable = true;<BR/> sp.Handshake = Handshake.None;<BR/> //textBox.Text = "";<BR/> sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);<BR/> sp.PinChanged += new SerialPinChangedEventHandler(plugged_in);<BR/> sp.Open();<BR/> }<BR/> catch (Exception ex)<BR/> { <BR/> BRlabel.Text = ex.Message;<BR/> }<BR/> //Text Read Finishes<BR/> StartCom.Hide();<BR/> Send.Show();<BR/> textBox.Show();<BR/> DBlabel.Text="";<BR/> Plabel.Text="";<BR/> SBlabel.Text="";<BR/> RTlabel.Text = "";<BR/> ComPrt.Text = "";<BR/> //BRlabel.Text = ""; <BR/> <BR/> }<BR/> private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)<BR/> {<BR/> <BR/> try<BR/> {<BR/> byte[] b = new byte[3];<BR/> for (int i = 0; i < 3; i++)<BR/> b[i] = (byte)sp.ReadByte();<BR/> string s = b.ToString();<BR/> MessageBox.Show("DATA RECIEVED: \n" + s);<BR/> <BR/> }<BR/> catch<BR/> {<BR/> Console.WriteLine("UH HUH!");<BR/> sp.Close();<BR/> }<BR/> Console.ReadLine();<BR/> }<BR/> private void plugged_in(object sender, SerialPinChangedEventArgs ea)<BR/> {<BR/> MessageBox.Show(" Device powered ON!/ OFF!");<BR/> }<BR/> <BR/> <BR/> }<BR/> <BR/>}<BR/>I'm gettin parameter count mismatch in main(Program.cs), in the line Application.Run(new Form1) which is removed when I comment the line BeginInvoke. <BR/><BR/>I'm new to C#.NET, please help.Anonymoushttps://www.blogger.com/profile/15480996974552080094noreply@blogger.comtag:blogger.com,1999:blog-8259613.post-90826554991937685002009-01-16T11:20:00.000+01:002009-01-16T11:20:00.000+01:00thanks, helped me a lot.thanks, helped me a lot.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-8259613.post-38134373514151787242008-12-26T10:49:00.000+01:002008-12-26T10:49:00.000+01:00Hi,Thanks for the great article. It helped me solv...Hi,<BR/><BR/>Thanks for the great article. It helped me solved my problem.<BR/><BR/>Cheers,<BR/><BR/>MonoAnonymousnoreply@blogger.comtag:blogger.com,1999:blog-8259613.post-19975054395140593612008-07-18T05:16:00.000+02:002008-07-18T05:16:00.000+02:00I ran into the same issues when upgrading vs2003 t...I ran into the same issues when upgrading vs2003 to vs2005. Fortunelty I had a collegue who had experience in delgate use to showed me what was needed to do. Even after seeing these example<BR/><BR/>It was just so simple after that. Haven't incountered any issues yet with the Invoke() command over the program however given each thread only updates a particular cell in the listveiw hence no thread is really fighting for the same real estate, may have something to do with it. Anyway here is my solution seems very easy now.<BR/><BR/>clsthread.cs<BR/><BR/>// All the code is in the thread.class no need to putanything in the main form<BR/><BR/> delegate void Updatelistview1Invoker(ListView listview1, int row, int column, string message);<BR/><BR/> private void MainThread_Updatelistview1(ListView listview1, int row, int column, string message)<BR/> {<BR/> listview1.Items[row].SubItems[column].Text = message;<BR/> }<BR/><BR/> public void Updatelistview1(ListView listview1, int row, int column, string message)<BR/> {<BR/> listview1.Invoke(new Updatelistview1Invoker(MainThread_Updatelistview1), new object[] { listview1,row,column,message});<BR/> }<BR/><BR/>// Call this <BR/><BR/>Updatelistview1(listview1, row, column, "Abort");henryvhttps://www.blogger.com/profile/03974758703949554759noreply@blogger.comtag:blogger.com,1999:blog-8259613.post-24913813382495743492007-08-08T14:42:00.000+02:002007-08-08T14:42:00.000+02:00tim:You're doing something strange here: this.EndI...tim:<BR/>You're doing something strange here: <BR/>this.EndInvoke(this.BeginInvoke(...))<BR/><BR/>Immedeately calling EndInvoke() on the result you get from BeginInvoke() is actually just the same as calling Invoke() in the first place! And it has the same downsides that I discussed in this post.Kristofhttps://www.blogger.com/profile/01727380410232817527noreply@blogger.comtag:blogger.com,1999:blog-8259613.post-33595145434028316442007-08-08T13:35:00.000+02:002007-08-08T13:35:00.000+02:00Instead of using a custom Invoker delegate you cou...Instead of using a custom Invoker delegate you could also use the System.Windows.Forms.MethodInvoker delegate...<BR/><BR/>The 'pattern' would be:<BR/><BR/>private void DoX(object input)<BR/>{<BR/> if (this.InvokeRequired)<BR/> {<BR/> this.EndInvoke(this.BeginInvoke(new MethodInvoker(delegate { this.DoX(input); })));<BR/> }<BR/> else<BR/> {<BR/> // perform actual work<BR/> }<BR/>}timvwhttps://www.blogger.com/profile/11373008902278757108noreply@blogger.comtag:blogger.com,1999:blog-8259613.post-78833707113581384862007-04-05T01:45:00.000+02:002007-04-05T01:45:00.000+02:00I deadlocked with Control.Invoke and Thread.Join, ...I deadlocked with Control.Invoke and Thread.Join, so it can easily happen, since Thread.Join is shown in the example code for threading.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-8259613.post-37799079411354265152007-04-02T11:11:00.000+02:002007-04-02T11:11:00.000+02:00Thank you very much - I immediately ran into a dea...Thank you very much - I immediately ran into a deadlock when trying to use Invoke(), nice to see that there's an easy way out.Anonymousnoreply@blogger.com