Reputation: 5627
I am attempting to change the Text property on a control from another thread. I am using this method to do this:
public static void InvokeIfRequired(this Control control, MethodInvoker action)
{
if (control.InvokeRequired)
{
try
{
control.Invoke(action);
}
catch (ObjectDisposedException) { }
catch (InvalidAsynchronousStateException) { }
}
else
{
action();
}
}
I am still getting a 'System.InvalidOperationException'
exception when using this method. When I break into this, I can see that control.InvokeRequired
is false
, but it looks like it is in fact being accessed from another thread ??
In the actual error message, it doesn't give me the same of the control that I am trying to invoke. Rather, it gives me the form in which the control resides, stating 'Form1 accessed from a thread other than the thread it was created on'.
I have trying passing the form to the InvokeIfRequired
method, but still Form1.InvokeRequired
is false
and the exception occurs. The control I am trying to invoke was created in the designer.
Here is the code I am using to edit the control:
private void StartUpdateThreads() // called from the Form ctor
{
new Thread(new ThreadStart(this.TimeUpdater)).Start();
new Thread(new ThreadStart(this.AccountBalanceUpdater)).Start();
}
private void TimeUpdater()
{
while (!this.IsDisposed)
{
Utilities.InvokeIfRequired(this, (MethodInvoker)(() =>
{
this.timestampLabel.Text = DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss");
}));
Thread.Sleep(250);
}
}
Here is the call stack:
MyApp.exe!MyApp.MyAppToolbar.TimeUpdater.AnonymousMethod__0() Line 133 + 0x41 bytes
MyApp.exe!MyApp.Utilities.InvokeIfRequired(System.Windows.Forms.Control control, System.Windows.Forms.MethodInvoker action) Line 34 + 0xb bytes
MyApp.exe!MyApp.MyAppToolbar.TimeUpdater() Line 131 + 0x49 bytes
Here is the stack trace:
at System.Windows.Forms.Control.get_Handle()\r\n
at System.Windows.Forms.Control.get_InternalHandle()\r\n
at System.Windows.Forms.Control.get_CreateParams()\r\n
at System.Windows.Forms.Label.get_CreateParams()\r\n
at System.Windows.Forms.Control.SizeFromClientSize(Int32 width, Int32 height)\r\n
at System.Windows.Forms.Control.SizeFromClientSize(Size clientSize)\r\n
at System.Windows.Forms.Label.GetBordersAndPadding()\r\n
at System.Windows.Forms.Label.GetPreferredSizeCore(Size proposedConstraints)\r\n
at System.Windows.Forms.Control.GetPreferredSize(Size proposedSize)\r\n
at System.Windows.Forms.Label.GetPreferredSize(Size proposedSize)\r\n
at System.Windows.Forms.Control.get_PreferredSize()\r\n
at System.Windows.Forms.Label.AdjustSize()\r\n
at System.Windows.Forms.Label.OnTextChanged(EventArgs e)\r\n
at System.Windows.Forms.Control.set_Text(String value)\r\n
at System.Windows.Forms.Label.set_Text(String value)\r\n
at MyApp.MyAppToolbar.<TimeUpdater>b__0() in PATH\\TO\\FILE.cs:line 133\r\n
at MyApp.Utilities.InvokeIfRequired(Control control, MethodInvoker action) in PATH\\TO\\FILE.cs:line 34\r\n MyApp.MyAppToolbar.TimeUpdater() in PATH\\TO\\FILE.cs:line 131\r\n
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)\r\n
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)\r\n
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)\r\n
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)\r\n
at System.Threading.ThreadHelper.ThreadStart()
Could someone point me in the right direction here ?
Upvotes: 0
Views: 245
Reputation: 35594
Reading the documentation on InvokeRequired
you can see that it returns false
when the control's handle hasn't been created yet. The documentation states that you need to check the value of IsHandleCreated
before.
And there's an issue on the destruction time as well, as Hans states above, so you might want to check if the control is already disposed when inside the correct thread.
Another approach would be to start the background threads when the controls are fully loaded, but again this makes InvokeIfRequired
not a general-purpose tool.
Upvotes: 2
Reputation: 4532
Hi sherlock i think this will be helpfull http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx
Upvotes: 0